diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c index 837495c59e..23c96646e7 100644 --- a/src/libcharon/config/child_cfg.c +++ b/src/libcharon/config/child_cfg.c @@ -266,81 +266,138 @@ METHOD(child_cfg_t, add_traffic_selector, void, } } +/** + * Create a copy of the traffic selectors in the given list, while resolving + * "dynamic" traffic selectors using the given hosts, if any. When not narrowing + * as initiator, we also replace TS in transport mode. + */ +static linked_list_t *resolve_dynamic_ts(private_child_cfg_t *this, + linked_list_t *list, + linked_list_t *hosts, + bool narrowing) +{ + enumerator_t *e1, *e2; + traffic_selector_t *ts1, *ts2; + linked_list_t *result; + host_t *host; + bool transport_mode; + + if (!hosts || !hosts->get_count(hosts)) + { + return list->clone_offset(list, offsetof(traffic_selector_t, clone)); + } + transport_mode = !narrowing && this->mode == MODE_TRANSPORT && + !has_option(this, OPT_PROXY_MODE); + + result = linked_list_create(); + e1 = list->create_enumerator(list); + while (e1->enumerate(e1, &ts1)) + { + /* set hosts if TS is dynamic or as initiator in transport mode */ + bool dynamic = ts1->is_dynamic(ts1); + if (!dynamic && !transport_mode) + { + result->insert_last(result, ts1->clone(ts1)); + continue; + } + e2 = hosts->create_enumerator(hosts); + while (e2->enumerate(e2, &host)) + { + if (!dynamic && !host->is_anyaddr(host) && + !ts1->includes(ts1, host)) + { /* for transport mode, we skip TS that don't match + * specific IPs */ + continue; + } + ts2 = ts1->clone(ts1); + if (dynamic || !host->is_anyaddr(host)) + { /* don't make regular TS larger than they were */ + ts2->set_address(ts2, host); + } + result->insert_last(result, ts2); + } + e2->destroy(e2); + } + e1->destroy(e1); + return result; +} + +/** + * Remove duplicate traffic selectors in the given list. + */ +static void remove_duplicate_ts(linked_list_t *list) +{ + enumerator_t *e1, *e2; + traffic_selector_t *ts1, *ts2; + + e1 = list->create_enumerator(list); + e2 = list->create_enumerator(list); + while (e1->enumerate(e1, &ts1)) + { + while (e2->enumerate(e2, &ts2)) + { + if (ts1 != ts2) + { + if (ts2->is_contained_in(ts2, ts1)) + { + list->remove_at(list, e2); + ts2->destroy(ts2); + list->reset_enumerator(list, e1); + break; + } + if (ts1->is_contained_in(ts1, ts2)) + { + list->remove_at(list, e1); + ts1->destroy(ts1); + break; + } + } + } + list->reset_enumerator(list, e2); + } + e1->destroy(e1); + e2->destroy(e2); +} + METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*, + private_child_cfg_t *this, bool local, linked_list_t *hosts) +{ + linked_list_t *result; + + result = resolve_dynamic_ts(this, local ? this->my_ts : this->other_ts, + hosts, FALSE); + remove_duplicate_ts(result); + return result; +} + +METHOD(child_cfg_t, select_traffic_selectors, linked_list_t*, private_child_cfg_t *this, bool local, linked_list_t *supplied, - linked_list_t *hosts, bool log) + linked_list_t *hosts) { enumerator_t *e1, *e2; traffic_selector_t *ts1, *ts2, *selected; - linked_list_t *result, *derived; - host_t *host; + linked_list_t *resolved, *result; result = linked_list_create(); - derived = linked_list_create(); - if (local) - { - e1 = this->my_ts->create_enumerator(this->my_ts); - } - else - { - e1 = this->other_ts->create_enumerator(this->other_ts); - } - /* in a first step, replace "dynamic" TS with the host list */ - while (e1->enumerate(e1, &ts1)) - { - if (hosts && hosts->get_count(hosts)) - { /* set hosts if TS is dynamic or as initiator in transport mode */ - bool dynamic = ts1->is_dynamic(ts1), - proxy_mode = has_option(this, OPT_PROXY_MODE); - if (dynamic || (this->mode == MODE_TRANSPORT && !proxy_mode && - !supplied)) - { - e2 = hosts->create_enumerator(hosts); - while (e2->enumerate(e2, &host)) - { - if (!dynamic && !host->is_anyaddr(host) && - !ts1->includes(ts1, host)) - { /* for transport mode, we skip TS that don't match - * specific IPs */ - continue; - } - ts2 = ts1->clone(ts1); - if (dynamic || !host->is_anyaddr(host)) - { /* don't make regular TS larger than they were */ - ts2->set_address(ts2, host); - } - derived->insert_last(derived, ts2); - } - e2->destroy(e2); - continue; - } - } - derived->insert_last(derived, ts1->clone(ts1)); - } - e1->destroy(e1); + resolved = resolve_dynamic_ts(this, local ? this->my_ts : this->other_ts, + hosts, supplied); + + DBG2(DBG_CFG, "%s traffic selectors for %s:", + supplied ? "selecting" : "proposing", local ? "us" : "other"); - if (log) - { - DBG2(DBG_CFG, "%s traffic selectors for %s:", - supplied ? "selecting" : "proposing", local ? "us" : "other"); - } if (!supplied) { - while (derived->remove_first(derived, (void**)&ts1) == SUCCESS) + while (resolved->remove_first(resolved, (void**)&ts1) == SUCCESS) { - if (log) - { - DBG2(DBG_CFG, " %R", ts1); - } + DBG2(DBG_CFG, " %R", ts1); result->insert_last(result, ts1); } - derived->destroy(derived); } else { - e1 = derived->create_enumerator(derived); + e1 = resolved->create_enumerator(resolved); e2 = supplied->create_enumerator(supplied); - /* enumerate all configured/derived selectors */ + /* enumerate all configured/resolved selectors */ while (e1->enumerate(e1, &ts1)) { /* enumerate all supplied traffic selectors */ @@ -349,14 +406,11 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*, selected = ts1->get_subset(ts1, ts2); if (selected) { - if (log) - { - DBG2(DBG_CFG, " config: %R, received: %R => match: %R", - ts1, ts2, selected); - } + DBG2(DBG_CFG, " config: %R, received: %R => match: %R", + ts1, ts2, selected); result->insert_last(result, selected); } - else if (log) + else { DBG2(DBG_CFG, " config: %R, received: %R => no match", ts1, ts2); @@ -368,7 +422,7 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*, e2->destroy(e2); /* check if we/peer did any narrowing, raise alert */ - e1 = derived->create_enumerator(derived); + e1 = resolved->create_enumerator(resolved); e2 = result->create_enumerator(result); while (e1->enumerate(e1, &ts1)) { @@ -382,38 +436,9 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*, e1->destroy(e1); e2->destroy(e2); - derived->destroy_offset(derived, offsetof(traffic_selector_t, destroy)); } - - /* remove any redundant traffic selectors in the list */ - e1 = result->create_enumerator(result); - e2 = result->create_enumerator(result); - while (e1->enumerate(e1, &ts1)) - { - while (e2->enumerate(e2, &ts2)) - { - if (ts1 != ts2) - { - if (ts2->is_contained_in(ts2, ts1)) - { - result->remove_at(result, e2); - ts2->destroy(ts2); - result->reset_enumerator(result, e1); - break; - } - if (ts1->is_contained_in(ts1, ts2)) - { - result->remove_at(result, e1); - ts1->destroy(ts1); - break; - } - } - } - result->reset_enumerator(result, e2); - } - e1->destroy(e1); - e2->destroy(e2); - + resolved->destroy_offset(resolved, offsetof(traffic_selector_t, destroy)); + remove_duplicate_ts(result); return result; } @@ -755,6 +780,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data) .get_name = _get_name, .add_traffic_selector = _add_traffic_selector, .get_traffic_selectors = _get_traffic_selectors, + .select_traffic_selectors = _select_traffic_selectors, .add_proposal = _add_proposal, .get_proposals = _get_proposals, .select_proposal = _select_proposal, diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h index 4a9a699df9..eb78b3d32f 100644 --- a/src/libcharon/config/child_cfg.h +++ b/src/libcharon/config/child_cfg.h @@ -119,26 +119,50 @@ struct child_cfg_t { traffic_selector_t *ts); /** - * Get a list of traffic selectors to use for the CHILD_SA. + * Get a list of configured traffic selectors to use for the CHILD_SA. * * The config contains two set of traffic selectors, one for the local * side, one for the remote side. + * + * Some traffic selectors may be "dynamic", meaning they are narrowed down + * to a specific address (host-to-host or virtual-IP setups). Use the + * "hosts" parameter to narrow such traffic selectors to an address. + * + * Returned list and its traffic selectors must be destroyed after use. + * + * Note that this method does not log anything. If logging is required, use + * select_traffic_selectors() without passing supplied traffic selectors. + * + * @param local TRUE for TS on local side, FALSE for remote + * @param hosts addresses to use for narrowing "dynamic" TS', host_t + * @return list containing the traffic selectors + */ + linked_list_t *(*get_traffic_selectors)(child_cfg_t *this, bool local, + linked_list_t *hosts); + + /** + * Select a list of traffic selectors to use for the CHILD_SA. + * + * The config contains two set of traffic selectors, one for the local + * side, one for the remote side. + * * If a list with traffic selectors is supplied, these are used to narrow - * down the traffic selector list to the greatest common divisor. - * Some traffic selector may be "dynamic", meaning they are narrowed down - * to a specific address (host-to-host or virtual-IP setups). Use - * the "host" parameter to narrow such traffic selectors to that address. - * Resulted list and its traffic selectors must be destroyed after use. + * down the traffic selector list to the greatest common subset. + * + * Some traffic selectors may be "dynamic", meaning they are narrowed down + * to a specific address (host-to-host or virtual-IP setups). Use the + * "hosts" parameter to narrow such traffic selectors to an address. + * + * Returned list and its traffic selectors must be destroyed after use. * * @param local TRUE for TS on local side, FALSE for remote * @param supplied list with TS to select from, or NULL * @param hosts addresses to use for narrowing "dynamic" TS', host_t - * @param log FALSE to avoid logging details about the selection * @return list containing the traffic selectors */ - linked_list_t *(*get_traffic_selectors)(child_cfg_t *this, bool local, - linked_list_t *supplied, - linked_list_t *hosts, bool log); + linked_list_t *(*select_traffic_selectors)(child_cfg_t *this, bool local, + linked_list_t *supplied, + linked_list_t *hosts); /** * Get the updown script to run for the CHILD_SA. diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c index c44f87025a..a0da017241 100644 --- a/src/libcharon/config/peer_cfg.c +++ b/src/libcharon/config/peer_cfg.c @@ -414,7 +414,7 @@ static u_int get_ts_match(child_cfg_t *cfg, bool local, } /* fetch configured TS list, narrowing dynamic TS */ - cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, hosts, TRUE); + cfg_list = cfg->select_traffic_selectors(cfg, local, NULL, hosts); /* use a round counter to rate leading TS with higher priority */ round = sup_list->get_count(sup_list); diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c index 85ff5830bc..d2afea708f 100644 --- a/src/libcharon/plugins/smp/smp.c +++ b/src/libcharon/plugins/smp/smp.c @@ -330,12 +330,10 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write xmlTextWriterStartElement(writer, "childconfig"); xmlTextWriterWriteElement(writer, "name", child_cfg->get_name(child_cfg)); - list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, - NULL, FALSE); + list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL); write_networks(writer, "local", list); list->destroy_offset(list, offsetof(traffic_selector_t, destroy)); - list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, - NULL, FALSE); + list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL); write_networks(writer, "remote", list); list->destroy_offset(list, offsetof(traffic_selector_t, destroy)); xmlTextWriterEndElement(writer); diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index 34d840f75a..49e5eba076 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -585,10 +585,9 @@ METHOD(stroke_list_t, status, void, children = peer_cfg->create_child_cfg_enumerator(peer_cfg); while (children->enumerate(children, &child_cfg)) { - my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, - NULL, NULL, FALSE); + my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL); other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, - NULL, NULL, FALSE); + NULL); fprintf(out, "%12s: child: %#R === %#R %N", child_cfg->get_name(child_cfg), my_ts, other_ts, ipsec_mode_names, child_cfg->get_mode(child_cfg)); @@ -621,10 +620,8 @@ METHOD(stroke_list_t, status, void, fprintf(out, "Shunted Connections:\n"); first = FALSE; } - my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, - NULL, FALSE); - other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, - NULL, FALSE); + my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL); + other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL); fprintf(out, "%12s: %#R === %#R %N\n", child_cfg->get_name(child_cfg), my_ts, other_ts, ipsec_mode_names, child_cfg->get_mode(child_cfg)); diff --git a/src/libcharon/plugins/unity/unity_narrow.c b/src/libcharon/plugins/unity/unity_narrow.c index 1a3c74935c..a0337a25ce 100644 --- a/src/libcharon/plugins/unity/unity_narrow.c +++ b/src/libcharon/plugins/unity/unity_narrow.c @@ -55,7 +55,7 @@ static void narrow_ts(child_cfg_t *cfg, traffic_selector_t *ts, received = linked_list_create(); received->insert_last(received, ts); - selected = cfg->get_traffic_selectors(cfg, FALSE, received, NULL, FALSE); + selected = cfg->select_traffic_selectors(cfg, FALSE, received, NULL); while (selected->remove_first(selected, (void**)&ts) == SUCCESS) { list->insert_last(list, ts); @@ -139,8 +139,7 @@ static void narrow_responder_post(child_cfg_t *child_cfg, linked_list_t *local) { ts->destroy(ts); } - configured = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL, - FALSE); + configured = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL); while (configured->remove_first(configured, (void**)&ts) == SUCCESS) { diff --git a/src/libcharon/plugins/unity/unity_provider.c b/src/libcharon/plugins/unity/unity_provider.c index ffdc723b17..133907ebf8 100644 --- a/src/libcharon/plugins/unity/unity_provider.c +++ b/src/libcharon/plugins/unity/unity_provider.c @@ -159,8 +159,7 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); while (enumerator->enumerate(enumerator, &child_cfg)) { - current = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL, - FALSE); + current = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL); while (current->remove_first(current, (void**)&ts) == SUCCESS) { if (use_ts(ts)) diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c index 628763e191..7bea7579b0 100644 --- a/src/libcharon/plugins/vici/vici_query.c +++ b/src/libcharon/plugins/vici/vici_query.c @@ -684,7 +684,7 @@ static void raise_policy_cfg(private_vici_query_t *this, u_int id, char *ike, list_label(b, NULL, cfg); b->begin_list(b, "local-ts"); - list = cfg->get_traffic_selectors(cfg, TRUE, NULL, NULL, FALSE); + list = cfg->get_traffic_selectors(cfg, TRUE, NULL); enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, &ts)) { @@ -695,7 +695,7 @@ static void raise_policy_cfg(private_vici_query_t *this, u_int id, char *ike, b->end_list(b /* local-ts */); b->begin_list(b, "remote-ts"); - list = cfg->get_traffic_selectors(cfg, FALSE, NULL, NULL, FALSE); + list = cfg->get_traffic_selectors(cfg, FALSE, NULL); enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, &ts)) { @@ -1002,8 +1002,7 @@ CALLBACK(list_conns, vici_message_t*, child_cfg->get_close_action(child_cfg)); b->begin_list(b, "local-ts"); - list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, - NULL, FALSE); + list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL); selectors = list->create_enumerator(list); while (selectors->enumerate(selectors, &ts)) { @@ -1014,8 +1013,7 @@ CALLBACK(list_conns, vici_message_t*, b->end_list(b /* local-ts */); b->begin_list(b, "remote-ts"); - list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, - NULL, FALSE); + list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL); selectors = list->create_enumerator(list); while (selectors->enumerate(selectors, &ts)) { diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c index 245d87af7f..3c4f721cae 100644 --- a/src/libcharon/sa/child_sa.c +++ b/src/libcharon/sa/child_sa.c @@ -2036,7 +2036,7 @@ static host_t* get_proxy_addr(child_cfg_t *config, host_t *ike, bool local) traffic_selector_t *ts; list = linked_list_create_with_items(ike, NULL); - ts_list = config->get_traffic_selectors(config, local, NULL, list, FALSE); + ts_list = config->get_traffic_selectors(config, local, list); list->destroy(list); enumerator = ts_list->create_enumerator(ts_list); diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c index ea54b24d21..686bc9ea96 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_mode.c +++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c @@ -540,8 +540,8 @@ static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local, linked_list_t *list, *hosts; hosts = get_dynamic_hosts(this->ike_sa, local); - list = this->config->get_traffic_selectors(this->config, - local, supplied, hosts, TRUE); + list = this->config->select_traffic_selectors(this->config, local, + supplied, hosts); hosts->destroy(hosts); if (list->get_first(list, (void**)&ts) == SUCCESS) { diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index 9efaed28f4..791ca4b361 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -468,14 +468,14 @@ static linked_list_t* narrow_ts(private_child_create_t *this, bool local, this->ike_sa->has_condition(this->ike_sa, cond)) { nat = get_transport_nat_ts(this, local, in); - ts = this->config->get_traffic_selectors(this->config, local, nat, - hosts, TRUE); + ts = this->config->select_traffic_selectors(this->config, local, nat, + hosts); nat->destroy_offset(nat, offsetof(traffic_selector_t, destroy)); } else { - ts = this->config->get_traffic_selectors(this->config, local, in, - hosts, TRUE); + ts = this->config->select_traffic_selectors(this->config, local, in, + hosts); } hosts->destroy(hosts); @@ -1461,21 +1461,21 @@ METHOD(task_t, build_i, status_t, } if (list->get_count(list)) { - this->tsi = this->config->get_traffic_selectors(this->config, - TRUE, NULL, list, TRUE); + this->tsi = this->config->select_traffic_selectors(this->config, TRUE, + NULL, list); list->destroy_offset(list, offsetof(host_t, destroy)); } else { /* no virtual IPs configured */ list->destroy(list); list = ike_sa_get_dynamic_hosts(this->ike_sa, TRUE); - this->tsi = this->config->get_traffic_selectors(this->config, - TRUE, NULL, list, TRUE); + this->tsi = this->config->select_traffic_selectors(this->config, TRUE, + NULL, list); list->destroy(list); } list = ike_sa_get_dynamic_hosts(this->ike_sa, FALSE); - this->tsr = this->config->get_traffic_selectors(this->config, - FALSE, NULL, list, TRUE); + this->tsr = this->config->select_traffic_selectors(this->config, FALSE, + NULL, list); list->destroy(list); if (this->packet_tsi) diff --git a/src/libcharon/sa/shunt_manager.c b/src/libcharon/sa/shunt_manager.c index c19b1fa396..b0c674c642 100644 --- a/src/libcharon/sa/shunt_manager.c +++ b/src/libcharon/sa/shunt_manager.c @@ -119,10 +119,8 @@ static bool install_shunt_policy(child_cfg_t *child) host_any6 = host_create_any(AF_INET6); hosts = linked_list_create_with_items(host_any, host_any6, NULL); - my_ts_list = child->get_traffic_selectors(child, TRUE, NULL, hosts, - FALSE); - other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, hosts, - FALSE); + my_ts_list = child->get_traffic_selectors(child, TRUE, hosts); + other_ts_list = child->get_traffic_selectors(child, FALSE, hosts); hosts->destroy(hosts); manual_prio = child->get_manual_prio(child); @@ -293,10 +291,8 @@ static void uninstall_shunt_policy(child_cfg_t *child) host_any6 = host_create_any(AF_INET6); hosts = linked_list_create_with_items(host_any, host_any6, NULL); - my_ts_list = child->get_traffic_selectors(child, TRUE, NULL, hosts, - FALSE); - other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, hosts, - FALSE); + my_ts_list = child->get_traffic_selectors(child, TRUE, hosts); + other_ts_list = child->get_traffic_selectors(child, FALSE, hosts); hosts->destroy(hosts); manual_prio = child->get_manual_prio(child); diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c index 5dcb49b497..7bd2c698f0 100644 --- a/src/libcharon/sa/trap_manager.c +++ b/src/libcharon/sa/trap_manager.c @@ -187,7 +187,7 @@ static bool dynamic_remote_ts(child_cfg_t *child) traffic_selector_t *ts; bool found = FALSE; - other_ts = child->get_traffic_selectors(child, FALSE, NULL, NULL, FALSE); + other_ts = child->get_traffic_selectors(child, FALSE, NULL); enumerator = other_ts->create_enumerator(other_ts); while (enumerator->enumerate(enumerator, &ts)) { @@ -215,8 +215,8 @@ static status_t install_trap(child_sa_t *child_sa, linked_list_t *local, child = child_sa->get_config(child_sa); - my_ts = child->get_traffic_selectors(child, TRUE, NULL, local, FALSE); - other_ts = child->get_traffic_selectors(child, FALSE, NULL, remote, FALSE); + my_ts = child->get_traffic_selectors(child, TRUE, local); + other_ts = child->get_traffic_selectors(child, FALSE, remote); /* we don't know the finally negotiated protocol (ESP|AH), we install * the SA with the protocol of the first proposal */