diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2015-11-18 14:49:27 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2015-11-18 14:49:27 +0100 |
commit | 1e980d6be0ef0e243c6fe82b5e855454b97e24a4 (patch) | |
tree | 0d59eec2ce2ed332434ae80fc78a44db9ad293c5 /src/libcharon/sa/ikev1 | |
parent | 5dca9ea0e2931f0e2a056c7964d311bcc30a01b8 (diff) | |
download | vyos-strongswan-1e980d6be0ef0e243c6fe82b5e855454b97e24a4.tar.gz vyos-strongswan-1e980d6be0ef0e243c6fe82b5e855454b97e24a4.zip |
Imported Upstream version 5.3.4
Diffstat (limited to 'src/libcharon/sa/ikev1')
-rw-r--r-- | src/libcharon/sa/ikev1/keymat_v1.c | 20 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/task_manager_v1.c | 110 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/mode_config.c | 4 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/quick_delete.c | 4 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/quick_mode.c | 6 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/xauth.c | 10 |
6 files changed, 122 insertions, 32 deletions
diff --git a/src/libcharon/sa/ikev1/keymat_v1.c b/src/libcharon/sa/ikev1/keymat_v1.c index f5a91dbeb..e428966ad 100644 --- a/src/libcharon/sa/ikev1/keymat_v1.c +++ b/src/libcharon/sa/ikev1/keymat_v1.c @@ -23,14 +23,9 @@ typedef struct private_keymat_v1_t private_keymat_v1_t; /** - * Max. number of IVs to track. + * Max. number of IVs/QMs to track. */ -#define MAX_IV 3 - -/** - * Max. number of Quick Modes to track. - */ -#define MAX_QM 2 +#define MAX_EXCHANGES_DEFAULT 3 /** * Data stored for IVs @@ -110,6 +105,11 @@ struct private_keymat_v1_t { * of QMs are tracked at the same time. Stores qm_data_t objects. */ linked_list_t *qms; + + /** + * Max. number of IVs/Quick Modes to track. + */ + int max_exchanges; }; @@ -874,7 +874,7 @@ static qm_data_t *lookup_quick_mode(private_keymat_v1_t *this, u_int32_t mid) } this->qms->insert_first(this->qms, found); /* remove least recently used state if maximum reached */ - if (this->qms->get_count(this->qms) > MAX_QM && + if (this->qms->get_count(this->qms) > this->max_exchanges && this->qms->remove_last(this->qms, (void**)&qm) == SUCCESS) { qm_data_destroy(qm); @@ -1048,7 +1048,7 @@ static iv_data_t *lookup_iv(private_keymat_v1_t *this, u_int32_t mid) } this->ivs->insert_first(this->ivs, found); /* remove least recently used IV if maximum reached */ - if (this->ivs->get_count(this->ivs) > MAX_IV && + if (this->ivs->get_count(this->ivs) > this->max_exchanges && this->ivs->remove_last(this->ivs, (void**)&iv) == SUCCESS) { iv_data_destroy(iv); @@ -1163,6 +1163,8 @@ keymat_v1_t *keymat_v1_create(bool initiator) .ivs = linked_list_create(), .qms = linked_list_create(), .initiator = initiator, + .max_exchanges = lib->settings->get_int(lib->settings, + "%s.max_ikev1_exchanges", MAX_EXCHANGES_DEFAULT, lib->ns), ); return &this->public; diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c index 678f99df1..3c601a4fa 100644 --- a/src/libcharon/sa/ikev1/task_manager_v1.c +++ b/src/libcharon/sa/ikev1/task_manager_v1.c @@ -752,6 +752,12 @@ static status_t build_response(private_task_manager_t *this, message_t *request) case ALREADY_DONE: cancelled = TRUE; break; + case INVALID_ARG: + if (task->get_type(task) == TASK_QUICK_MODE) + { /* not responsible for this exchange */ + continue; + } + /* FALL */ case FAILED: default: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); @@ -929,6 +935,28 @@ static bool have_quick_mode_task(private_task_manager_t *this, u_int32_t mid) } /** + * Check if we still have an aggressive mode task queued + */ +static bool have_aggressive_mode_task(private_task_manager_t *this) +{ + enumerator_t *enumerator; + task_t *task; + bool found = FALSE; + + enumerator = this->passive_tasks->create_enumerator(this->passive_tasks); + while (enumerator->enumerate(enumerator, &task)) + { + if (task->get_type(task) == TASK_AGGRESSIVE_MODE) + { + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + return found; +} + +/** * handle an incoming request message */ static status_t process_request(private_task_manager_t *this, @@ -1034,6 +1062,12 @@ static status_t process_request(private_task_manager_t *this, case ALREADY_DONE: send_response = FALSE; break; + case INVALID_ARG: + if (task->get_type(task) == TASK_QUICK_MODE) + { /* not responsible for this exchange */ + continue; + } + /* FALL */ case FAILED: default: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); @@ -1061,6 +1095,22 @@ static status_t process_request(private_task_manager_t *this, * the same message again. */ clear_packets(this->responding.packets); } + if (this->queued && + this->queued->get_exchange_type(this->queued) == INFORMATIONAL_V1) + { + message_t *queued; + status_t status; + + queued = this->queued; + this->queued = NULL; + status = this->public.task_manager.process_message( + &this->public.task_manager, queued); + queued->destroy(queued); + if (status == DESTROY_ME) + { + return status; + } + } if (this->passive_tasks->get_count(this->passive_tasks) == 0 && this->queued_tasks->get_count(this->queued_tasks) > 0) { @@ -1133,7 +1183,8 @@ static status_t process_response(private_task_manager_t *this, this->initiating.type = EXCHANGE_TYPE_UNDEFINED; clear_packets(this->initiating.packets); - if (this->queued && this->active_tasks->get_count(this->active_tasks) == 0) + if (this->queued && !this->active_tasks->get_count(this->active_tasks) && + this->queued->get_exchange_type(this->queued) == TRANSACTION) { queued = this->queued; this->queued = NULL; @@ -1228,6 +1279,29 @@ static status_t parse_message(private_task_manager_t *this, message_t *msg) return status; } +/** + * Queue the given message if possible + */ +static status_t queue_message(private_task_manager_t *this, message_t *msg) +{ + if (this->queued) + { + DBG1(DBG_IKE, "ignoring %N request, queue full", + exchange_type_names, msg->get_exchange_type(msg)); + return FAILED; + } + this->queued = message_create_from_packet(msg->get_packet(msg)); + if (this->queued->parse_header(this->queued) != SUCCESS) + { + this->queued->destroy(this->queued); + this->queued = NULL; + return FAILED; + } + DBG1(DBG_IKE, "queueing %N request as tasks still active", + exchange_type_names, msg->get_exchange_type(msg)); + return SUCCESS; +} + METHOD(task_manager_t, process_message, status_t, private_task_manager_t *this, message_t *msg) { @@ -1328,25 +1402,29 @@ METHOD(task_manager_t, process_message, status_t, } } - if (msg->get_exchange_type(msg) == TRANSACTION && - this->active_tasks->get_count(this->active_tasks)) - { /* main mode not yet complete, queue XAuth/Mode config tasks */ - if (this->queued) + /* drop XAuth/Mode Config/Quick Mode messages until we received the last + * Aggressive Mode message. since Informational messages are not + * retransmitted we queue them. */ + if (have_aggressive_mode_task(this)) + { + if (msg->get_exchange_type(msg) == INFORMATIONAL_V1) { - DBG1(DBG_IKE, "ignoring additional %N request, queue full", - exchange_type_names, TRANSACTION); - return SUCCESS; + return queue_message(this, msg); } - this->queued = message_create_from_packet(msg->get_packet(msg)); - if (this->queued->parse_header(this->queued) != SUCCESS) + else if (msg->get_exchange_type(msg) != AGGRESSIVE) { - this->queued->destroy(this->queued); - this->queued = NULL; + DBG1(DBG_IKE, "ignoring %N request while phase 1 is incomplete", + exchange_type_names, msg->get_exchange_type(msg)); return FAILED; } - DBG1(DBG_IKE, "queueing %N request as tasks still active", - exchange_type_names, TRANSACTION); - return SUCCESS; + } + + /* queue XAuth/Mode Config messages unless the Main Mode exchange we + * initiated is complete */ + if (msg->get_exchange_type(msg) == TRANSACTION && + this->active_tasks->get_count(this->active_tasks)) + { + return queue_message(this, msg); } msg->set_request(msg, TRUE); @@ -1724,6 +1802,8 @@ METHOD(task_manager_t, queue_dpd, void, pow(this->retransmit_base, retransmit)); } } + /* compensate for the already elapsed dpd delay */ + t -= 1000 * peer_cfg->get_dpd(peer_cfg); /* schedule DPD timeout job */ lib->scheduler->schedule_job_ms(lib->scheduler, diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.c b/src/libcharon/sa/ikev1/tasks/mode_config.c index d0994a961..a03477e18 100644 --- a/src/libcharon/sa/ikev1/tasks/mode_config.c +++ b/src/libcharon/sa/ikev1/tasks/mode_config.c @@ -482,7 +482,9 @@ static host_t *assign_migrated_vip(linked_list_t *migrated, host_t *requested) enumerator = migrated->create_enumerator(migrated); while (enumerator->enumerate(enumerator, &vip)) { - if (vip->ip_equals(vip, requested)) + if (vip->ip_equals(vip, requested) || + (requested->is_anyaddr(requested) && + requested->get_family(requested) == vip->get_family(vip))) { migrated->remove_at(migrated, enumerator); found = vip; diff --git a/src/libcharon/sa/ikev1/tasks/quick_delete.c b/src/libcharon/sa/ikev1/tasks/quick_delete.c index 1b95a8b11..ade59a2dd 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_delete.c +++ b/src/libcharon/sa/ikev1/tasks/quick_delete.c @@ -115,7 +115,7 @@ static bool delete_child(private_quick_delete_t *this, protocol_id_t protocol, if (this->expired) { DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} " - "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", + "with SPIs %.8x_i %.8x_o and TS %#R === %#R", child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa), ntohl(child_sa->get_spi(child_sa, TRUE)), ntohl(child_sa->get_spi(child_sa, FALSE)), my_ts, other_ts); @@ -126,7 +126,7 @@ static bool delete_child(private_quick_delete_t *this, protocol_id_t protocol, child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out, NULL); DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs " - "%.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R", + "%.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R === %#R", child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa), ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in, ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out, diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c index d6a3f2cd1..e7d26443b 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_mode.c +++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c @@ -388,7 +388,7 @@ static bool install(private_quick_mode_t *this) this->child_sa->create_ts_enumerator(this->child_sa, FALSE)); DBG0(DBG_IKE, "CHILD_SA %s{%d} established " - "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", + "with SPIs %.8x_i %.8x_o and TS %#R === %#R", this->child_sa->get_name(this->child_sa), this->child_sa->get_unique_id(this->child_sa), ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), @@ -1026,7 +1026,7 @@ METHOD(task_t, process_r, status_t, { if (this->mid && this->mid != message->get_message_id(message)) { /* not responsible for this quick mode exchange */ - return NEED_MORE; + return INVALID_ARG; } switch (this->state) @@ -1200,7 +1200,7 @@ METHOD(task_t, build_r, status_t, { if (this->mid && this->mid != message->get_message_id(message)) { /* not responsible for this quick mode exchange */ - return NEED_MORE; + return INVALID_ARG; } switch (this->state) diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c index a770e90ff..c0c91574c 100644 --- a/src/libcharon/sa/ikev1/tasks/xauth.c +++ b/src/libcharon/sa/ikev1/tasks/xauth.c @@ -271,7 +271,10 @@ static bool add_auth_cfg(private_xauth_t *this, identification_t *id, bool local auth = auth_cfg_create(); auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH); - auth->add(auth, AUTH_RULE_XAUTH_IDENTITY, id->clone(id)); + if (id) + { + auth->add(auth, AUTH_RULE_XAUTH_IDENTITY, id->clone(id)); + } auth->merge(auth, this->ike_sa->get_auth_cfg(this->ike_sa, local), FALSE); this->ike_sa->add_auth_cfg(this->ike_sa, local, auth); @@ -342,7 +345,10 @@ METHOD(task_t, build_i, status_t, break; case SUCCESS: DESTROY_IF(cp); - this->status = XAUTH_OK; + if (add_auth_cfg(this, NULL, FALSE) && allowed(this)) + { + this->status = XAUTH_OK; + } this->public.task.process = _process_i_status; return build_i_status(this, message); default: |