diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/sa/task_manager_v1.c | 71 |
1 files changed, 47 insertions, 24 deletions
diff --git a/src/libcharon/sa/task_manager_v1.c b/src/libcharon/sa/task_manager_v1.c index 99263aa5d..41976986e 100644 --- a/src/libcharon/sa/task_manager_v1.c +++ b/src/libcharon/sa/task_manager_v1.c @@ -55,6 +55,11 @@ struct private_task_manager_t { ike_sa_t *ike_sa; /** + * RNG to create message IDs + */ + rng_t *rng; + + /** * Exchange we are currently handling as responder */ struct { @@ -112,11 +117,6 @@ struct private_task_manager_t { linked_list_t *passive_tasks; /** - * the task manager has been reset - */ - bool reset; - - /** * Number of times we retransmit messages before giving up */ u_int retransmit_tries; @@ -187,7 +187,13 @@ METHOD(task_manager_t, initiate, status_t, message_t *message; host_t *me, *other; status_t status; - exchange_type_t exchange = 0; + exchange_type_t exchange = EXCHANGE_TYPE_UNDEFINED; + + if (!this->rng) + { + DBG1(DBG_IKE, "no RNG supported"); + return FAILED; + } if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED) { @@ -232,7 +238,7 @@ METHOD(task_manager_t, initiate, status_t, enumerator->destroy(enumerator); } - if (exchange == 0) + if (exchange == EXCHANGE_TYPE_UNDEFINED) { DBG2(DBG_IKE, "nothing to initiate"); /* nothing to do yet... */ @@ -245,7 +251,9 @@ METHOD(task_manager_t, initiate, status_t, message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION); if (exchange != ID_PROT) { - /* TODO-IKEv1: Set random message id */ + this->rng->get_bytes(this->rng, sizeof(this->initiating.mid), + (void*)&this->initiating.mid); + message->set_message_id(message, this->initiating.mid); } message->set_source(message, me->clone(me)); message->set_destination(message, other->clone(other)); @@ -333,7 +341,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request) /* send response along the path the request came in */ message->set_source(message, me->clone(me)); message->set_destination(message, other->clone(other)); - message->set_message_id(message, this->responding.mid); + message->set_message_id(message, request->get_message_id(request)); message->set_request(message, FALSE); enumerator = this->passive_tasks->create_enumerator(this->passive_tasks); @@ -510,11 +518,17 @@ static status_t process_response(private_task_manager_t *this, METHOD(task_manager_t, process_message, status_t, private_task_manager_t *this, message_t *msg) { - if (this->active_tasks->get_count(this->active_tasks) == 0) + u_int32_t hash, mid; + + mid = msg->get_message_id(msg); + hash = chunk_hash(msg->get_packet_data(msg)); + + if ((mid && mid == this->initiating.mid) || + (this->initiating.mid == 0 && + this->active_tasks->get_count(this->active_tasks))) { - /* TODO-IKEv1: detect mainmode retransmission */ - charon->bus->message(charon->bus, msg, TRUE); - if (process_request(this, msg) != SUCCESS) + charon->bus->message(charon->bus, msg, FALSE); + if (process_response(this, msg) != SUCCESS) { flush(this); return DESTROY_ME; @@ -522,12 +536,28 @@ METHOD(task_manager_t, process_message, status_t, } else { - charon->bus->message(charon->bus, msg, FALSE); - if (process_response(this, msg) != SUCCESS) + if ((mid && mid == this->responding.mid) || + hash == this->responding.mid) + { + DBG1(DBG_IKE, "received retransmit of request with ID %d, " + "retransmitting response", mid); + charon->sender->send(charon->sender, + this->responding.packet->clone(this->responding.packet)); + return SUCCESS; + } + + charon->bus->message(charon->bus, msg, TRUE); + if (process_request(this, msg) != SUCCESS) { flush(this); return DESTROY_ME; } + + if (!mid) + { + mid = hash; + } + this->responding.mid = mid; } return SUCCESS; } @@ -564,20 +594,11 @@ METHOD(task_manager_t, busy, bool, METHOD(task_manager_t, incr_mid, void, private_task_manager_t *this, bool initiate) { - if (initiate) - { - this->initiating.mid++; - } - else - { - this->responding.mid++; - } } METHOD(task_manager_t, reset, void, private_task_manager_t *this, u_int32_t initiate, u_int32_t respond) { - } METHOD(task_manager_t, create_task_enumerator, enumerator_t*, @@ -607,6 +628,7 @@ METHOD(task_manager_t, destroy, void, DESTROY_IF(this->responding.packet); DESTROY_IF(this->initiating.packet); + DESTROY_IF(this->rng); free(this); } @@ -634,6 +656,7 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa) }, .ike_sa = ike_sa, .initiating.type = EXCHANGE_TYPE_UNDEFINED, + .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK), .queued_tasks = linked_list_create(), .active_tasks = linked_list_create(), .passive_tasks = linked_list_create(), |