diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/bus/bus.h | 2 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/quick_mode.c | 22 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_create.c | 27 |
3 files changed, 48 insertions, 3 deletions
diff --git a/src/libcharon/bus/bus.h b/src/libcharon/bus/bus.h index 9f820e62f..aba8acdbd 100644 --- a/src/libcharon/bus/bus.h +++ b/src/libcharon/bus/bus.h @@ -111,6 +111,8 @@ enum narrow_hook_t { NARROW_INITIATOR_PRE_AUTH, /** invoked as responder during exchange, peer is authenticated */ NARROW_RESPONDER, + /** invoked as responder after exchange, peer is authenticated */ + NARROW_RESPONDER_POST, /** invoked as initiator after exchange, follows a INITIATOR_PRE_NOAUTH */ NARROW_INITIATOR_POST_NOAUTH, /** invoked as initiator after exchange, follows a INITIATOR_PRE_AUTH */ diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c index 73a23f4ea..8f2d192a0 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_mode.c +++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c @@ -214,7 +214,7 @@ static bool install(private_quick_mode_t *this) else { charon->bus->narrow(charon->bus, this->child_sa, - NARROW_RESPONDER, tsr, tsi); + NARROW_RESPONDER_POST, tsr, tsi); } if (tsi->get_count(tsi) == 0 || tsr->get_count(tsr) == 0) { @@ -419,7 +419,7 @@ static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local, supplied, host); if (list->get_first(list, (void**)&ts) == SUCCESS) { - if (list->get_count(list) > 1) + if (this->initiator && list->get_count(list) > 1) { DBG1(DBG_IKE, "configuration has more than one %s traffic selector," " using first only", local ? "local" : "remote"); @@ -974,6 +974,24 @@ METHOD(task_t, process_r, status_t, this->ike_sa->get_my_host(this->ike_sa), this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid, this->udp); + + tsi = linked_list_create(); + tsr = linked_list_create(); + tsi->insert_last(tsi, this->tsi); + tsr->insert_last(tsr, this->tsr); + this->tsi = this->tsr = NULL; + charon->bus->narrow(charon->bus, this->child_sa, + NARROW_RESPONDER, tsr, tsi); + if (tsi->remove_first(tsi, (void**)&this->tsi) != SUCCESS || + tsr->remove_first(tsr, (void**)&this->tsr) != SUCCESS) + { + tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy)); + tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy)); + return send_notify(this, INVALID_ID_INFORMATION); + } + tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy)); + tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy)); + return NEED_MORE; } case QM_NEGOTIATED: diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index d7d912fdc..3520760b0 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -516,7 +516,32 @@ static status_t select_and_install(private_child_create_t *this, return FAILED; } - status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts); + if (this->initiator) + { + status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts); + } + else + { + /* use a copy of the traffic selectors, as the POST hook should not + * change payloads */ + my_ts = this->tsr->clone_offset(this->tsr, + offsetof(traffic_selector_t, clone)); + other_ts = this->tsi->clone_offset(this->tsi, + offsetof(traffic_selector_t, clone)); + charon->bus->narrow(charon->bus, this->child_sa, + NARROW_RESPONDER_POST, my_ts, other_ts); + if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0) + { + status = FAILED; + } + else + { + status = this->child_sa->add_policies(this->child_sa, + my_ts, other_ts); + } + my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy)); + other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy)); + } if (status != SUCCESS) { DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel"); |