diff options
Diffstat (limited to 'src/charon/sa/ike_sa.c')
-rw-r--r-- | src/charon/sa/ike_sa.c | 246 |
1 files changed, 113 insertions, 133 deletions
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 5290bde64..c012ce82b 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -42,6 +42,7 @@ #include <sa/states/responder_init.h> #include <queues/jobs/retransmit_request_job.h> #include <queues/jobs/delete_established_ike_sa_job.h> +#include <queues/jobs/delete_half_open_ike_sa_job.h> @@ -186,43 +187,45 @@ struct private_ike_sa_t { * A logger for this IKE_SA. */ logger_t *logger; - - /** - * Resends the last sent reply. - * - * @param this calling object - */ - status_t (*resend_last_reply) (private_ike_sa_t *this); }; /** * Implementation of ike_sa_t.process_message. */ -static status_t process_message (private_ike_sa_t *this, message_t *message) +static status_t process_message(private_ike_sa_t *this, message_t *message) { u_int32_t message_id; exchange_type_t exchange_type; bool is_request; - /* We must process each request or response from remote host */ - + /* Find out type of message (request or response) */ is_request = message->get_request(message); exchange_type = message->get_exchange_type(message); - + this->logger->log(this->logger, CONTROL|LEVEL1, "Process %s of exchange type %s", (is_request) ? "request" : "response",mapping_find(exchange_type_m,exchange_type)); - + message_id = message->get_message_id(message); - + /* * It has to be checked, if the message has to be resent cause of lost packets! */ if (is_request && (message_id == (this->message_id_in - 1))) { - /* Message can be resent ! */ - this->logger->log(this->logger, CONTROL|LEVEL1, "Resent request detected. Send stored reply."); - return (this->resend_last_reply(this)); + /* resend last message, if any */ + if (this->last_responded_message) + { + packet_t *packet = this->last_responded_message->get_packet(this->last_responded_message); + this->logger->log(this->logger, CONTROL|LEVEL1, "Resent request detected. Send stored reply."); + charon->send_queue->add(charon->send_queue, packet); + return SUCCESS; + } + else + { + /* somebody does something nasty here... */ + return FAILED; + } } /* Now, the message id is checked for request AND reply */ @@ -253,7 +256,7 @@ static status_t process_message (private_ike_sa_t *this, message_t *message) * The specific state object is responsible to check if a message can be received in * the state it represents. * The current state is also responsible to change the state object to the next state - * by calling protected_ike_sa_t.set_new_state*/ + * by calling protected_ike_sa_t.set_new_state*/ return this->current_state->process_message(this->current_state,message); } @@ -269,7 +272,7 @@ static void build_message(private_ike_sa_t *this, exchange_type_t type, bool req other = this->connection->get_other_host(this->connection); this->logger->log(this->logger, CONTROL|LEVEL2, "Build empty message"); - new_message = message_create(); + new_message = message_create(); new_message->set_source(new_message, me->clone(me)); new_message->set_destination(new_message, other->clone(other)); new_message->set_exchange_type(new_message, type); @@ -301,55 +304,6 @@ static status_t initiate_connection(private_ike_sa_t *this, connection_t *connec } /** - * Implementation of ike_sa_t.send_delete_ike_sa_request. - */ -static void send_delete_ike_sa_request (private_ike_sa_t *this) -{ - message_t *informational_request; - delete_payload_t *delete_payload; - crypter_t *crypter; - signer_t *signer; - packet_t *packet; - status_t status; - - if (this->current_state->get_state(this->current_state) != IKE_SA_ESTABLISHED) - { - return; - } - - /* build empty INFORMATIONAL message */ - this->protected.build_message(&(this->protected), INFORMATIONAL, TRUE, &informational_request); - - delete_payload = delete_payload_create(); - delete_payload->set_protocol_id(delete_payload, PROTO_IKE); - - informational_request->add_payload(informational_request,(payload_t *)delete_payload); - - if (this->ike_sa_id->is_initiator(this->ike_sa_id)) - { - crypter = this->crypter_initiator; - signer = this->signer_initiator; - } - else - { - crypter = this->crypter_responder; - signer = this->signer_responder; - } - - status = informational_request->generate(informational_request, - crypter, - signer, &packet); - informational_request->destroy(informational_request); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "Could not generate packet from message"); - return ; - } - - charon->send_queue->add(charon->send_queue,packet); -} - -/** * Implementation of ike_sa_t.get_id. */ static ike_sa_id_t* get_id(private_ike_sa_t *this) @@ -390,20 +344,6 @@ static identification_t* get_other_id(private_ike_sa_t *this) } /** - * Implementation of private_ike_sa_t.resend_last_reply. - */ -static status_t resend_last_reply(private_ike_sa_t *this) -{ - packet_t *packet; - - this->logger->log(this->logger, CONTROL | LEVEL1, "Going to retransmit last reply"); - packet = this->last_responded_message->get_packet(this->last_responded_message); - charon->send_queue->add(charon->send_queue, packet); - - return SUCCESS; -} - -/** * Implementation of ike_sa_t.retransmit_request. */ status_t retransmit_request (private_ike_sa_t *this, u_int32_t message_id) @@ -431,22 +371,30 @@ status_t retransmit_request (private_ike_sa_t *this, u_int32_t message_id) return SUCCESS; } + +/** + * Implementation of ike_sa_t.get_state. + */ +static ike_sa_state_t get_state(private_ike_sa_t *this) +{ + return this->current_state->get_state(this->current_state); +} /** * Implementation of protected_ike_sa_t.set_new_state. */ -static void set_new_state (private_ike_sa_t *this, state_t *state) +static void set_new_state(private_ike_sa_t *this, state_t *state) { this->logger->log(this->logger, CONTROL, "statechange: %s => %s", - mapping_find(ike_sa_state_m,this->current_state->get_state(this->current_state)), - mapping_find(ike_sa_state_m,state->get_state(state))); + mapping_find(ike_sa_state_m, get_state(this)), + mapping_find(ike_sa_state_m, state->get_state(state))); this->current_state = state; } /** * Implementation of protected_ike_sa_t.get_connection. */ -static connection_t *get_connection (private_ike_sa_t *this) +static connection_t *get_connection(private_ike_sa_t *this) { return this->connection; } @@ -454,7 +402,7 @@ static connection_t *get_connection (private_ike_sa_t *this) /** * Implementation of protected_ike_sa_t.set_connection. */ -static void set_connection (private_ike_sa_t *this,connection_t * connection) +static void set_connection(private_ike_sa_t *this,connection_t * connection) { this->connection = connection; } @@ -462,7 +410,7 @@ static void set_connection (private_ike_sa_t *this,connection_t * connection) /** * Implementation of protected_ike_sa_t.get_policy. */ -static policy_t *get_policy (private_ike_sa_t *this) +static policy_t *get_policy(private_ike_sa_t *this) { return this->policy; } @@ -470,7 +418,7 @@ static policy_t *get_policy (private_ike_sa_t *this) /** * Implementation of protected_ike_sa_t.set_policy. */ -static void set_policy (private_ike_sa_t *this,policy_t * policy) +static void set_policy(private_ike_sa_t *this,policy_t * policy) { this->policy = policy; } @@ -478,7 +426,7 @@ static void set_policy (private_ike_sa_t *this,policy_t * policy) /** * Implementation of protected_ike_sa_t.get_prf. */ -static prf_t *get_prf (private_ike_sa_t *this) +static prf_t *get_prf(private_ike_sa_t *this) { return this->prf; } @@ -486,7 +434,7 @@ static prf_t *get_prf (private_ike_sa_t *this) /** * Implementation of protected_ike_sa_t.get_prf. */ -static prf_t *get_child_prf (private_ike_sa_t *this) +static prf_t *get_child_prf(private_ike_sa_t *this) { return this->child_prf; } @@ -494,7 +442,7 @@ static prf_t *get_child_prf (private_ike_sa_t *this) /** * Implementation of protected_ike_sa_t.get_prf_auth_i. */ -static prf_t *get_prf_auth_i (private_ike_sa_t *this) +static prf_t *get_prf_auth_i(private_ike_sa_t *this) { return this->prf_auth_i; } @@ -502,7 +450,7 @@ static prf_t *get_prf_auth_i (private_ike_sa_t *this) /** * Implementation of protected_ike_sa_t.get_prf_auth_r. */ -static prf_t *get_prf_auth_r (private_ike_sa_t *this) +static prf_t *get_prf_auth_r(private_ike_sa_t *this) { return this->prf_auth_r; } @@ -701,7 +649,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d /** * Implementation of protected_ike_sa_t.get_randomizer. */ -static randomizer_t *get_randomizer (private_ike_sa_t *this) +static randomizer_t *get_randomizer(private_ike_sa_t *this) { return this->randomizer; } @@ -709,7 +657,7 @@ static randomizer_t *get_randomizer (private_ike_sa_t *this) /** * Implementation of protected_ike_sa_t.get_crypter_initiator. */ -static crypter_t *get_crypter_initiator (private_ike_sa_t *this) +static crypter_t *get_crypter_initiator(private_ike_sa_t *this) { return this->crypter_initiator; } @@ -717,7 +665,7 @@ static crypter_t *get_crypter_initiator (private_ike_sa_t *this) /** * Implementation of protected_ike_sa_t.get_signer_initiator. */ -static signer_t *get_signer_initiator (private_ike_sa_t *this) +static signer_t *get_signer_initiator(private_ike_sa_t *this) { return this->signer_initiator; } @@ -733,7 +681,7 @@ static crypter_t *get_crypter_responder(private_ike_sa_t *this) /** * Implementation of protected_ike_sa_t.get_signer_responder. */ -static signer_t *get_signer_responder (private_ike_sa_t *this) +static signer_t *get_signer_responder(private_ike_sa_t *this) { return this->signer_responder; } @@ -741,7 +689,7 @@ static signer_t *get_signer_responder (private_ike_sa_t *this) /** * Implementation of protected_ike_sa_t.send_request. */ -static status_t send_request (private_ike_sa_t *this,message_t * message) +static status_t send_request(private_ike_sa_t *this, message_t *message) { retransmit_request_job_t *retransmit_job; u_int32_t timeout; @@ -783,29 +731,25 @@ static status_t send_request (private_ike_sa_t *this,message_t * message) this->message_id_out); charon->send_queue->add(charon->send_queue, packet); + /* replace last message for retransmit with current */ if (this->last_requested_message != NULL) { - /* destroy message */ this->last_requested_message->destroy(this->last_requested_message); - } - + } this->logger->log(this->logger, CONTROL|LEVEL3, "Replace last requested message with new one"); this->last_requested_message = message; - retransmit_job = retransmit_request_job_create(this->message_id_out,this->ike_sa_id); - - status = charon->configuration->get_retransmit_timeout (charon->configuration, - retransmit_job->get_retransmit_count(retransmit_job),&timeout); - + /* schedule a job for retransmission */ + status = charon->configuration->get_retransmit_timeout(charon->configuration, 0, &timeout); if (status != SUCCESS) { this->logger->log(this->logger, CONTROL|LEVEL2, "No retransmit job for message created!"); - retransmit_job->destroy(retransmit_job); } else { - this->logger->log(this->logger, CONTROL|LEVEL2, "Request will be retransmitted in %d ms.",timeout); - charon->event_queue->add_relative(charon->event_queue,(job_t *) retransmit_job,timeout); + this->logger->log(this->logger, CONTROL|LEVEL2, "Request will be retransmitted in %d ms.", timeout); + retransmit_job = retransmit_request_job_create(this->message_id_out, this->ike_sa_id); + charon->event_queue->add_relative(charon->event_queue, (job_t *)retransmit_job, timeout); } /* message counter can now be increased */ @@ -819,7 +763,7 @@ static status_t send_request (private_ike_sa_t *this,message_t * message) /** * Implementation of protected_ike_sa_t.send_response. */ -static status_t send_response (private_ike_sa_t *this,message_t * message) +static status_t send_response(private_ike_sa_t *this, message_t *message) { crypter_t *crypter; signer_t *signer; @@ -832,7 +776,6 @@ static status_t send_response (private_ike_sa_t *this,message_t * message) return FAILED; } - if (this->ike_sa_id->is_initiator(this->ike_sa_id)) { crypter = this->crypter_initiator; @@ -922,7 +865,7 @@ static void set_last_replied_message_id (private_ike_sa_t *this,u_int32_t messag /** * Implementation of protected_ike_sa_t.get_last_responded_message. */ -static message_t * get_last_responded_message (private_ike_sa_t *this) +static message_t *get_last_responded_message (private_ike_sa_t *this) { return this->last_responded_message; } @@ -930,23 +873,15 @@ static message_t * get_last_responded_message (private_ike_sa_t *this) /** * Implementation of protected_ike_sa_t.get_last_requested_message. */ -static message_t * get_last_requested_message (private_ike_sa_t *this) +static message_t *get_last_requested_message(private_ike_sa_t *this) { return this->last_requested_message; } /** - * Implementation of ike_sa_t.get_state. - */ -static ike_sa_state_t get_state (private_ike_sa_t *this) -{ - return this->current_state->get_state(this->current_state); -} - -/** * Implementation of protected_ike_sa_t.add_child_sa. */ -static void add_child_sa (private_ike_sa_t *this, child_sa_t *child_sa) +static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa) { this->child_sas->insert_last(this->child_sas, child_sa); } @@ -954,7 +889,7 @@ static void add_child_sa (private_ike_sa_t *this, child_sa_t *child_sa) /** * Implementation of protected_ike_sa_t.reset_message_buffers. */ -static void reset_message_buffers (private_ike_sa_t *this) +static void reset_message_buffers(private_ike_sa_t *this) { this->logger->log(this->logger, CONTROL|LEVEL2, "Reset message counters and destroy stored messages"); /* destroy stored requested message */ @@ -983,6 +918,8 @@ static void log_status(private_ike_sa_t *this, logger_t *logger, char *name) { iterator_t *iterator; child_sa_t *child_sa; + host_t *my_host, *other_host; + identification_t *my_id, *other_id; /* only log if name == NULL or name == connection_name */ if (name) @@ -997,11 +934,11 @@ static void log_status(private_ike_sa_t *this, logger_t *logger, char *name) name = this->connection->get_name(this->connection); } - host_t *my_host = this->connection->get_my_host(this->connection); - host_t *other_host = this->connection->get_other_host(this->connection); + my_host = this->connection->get_my_host(this->connection); + other_host = this->connection->get_other_host(this->connection); - identification_t *my_id = this->connection->get_my_id(this->connection); - identification_t *other_id = this->connection->get_other_id(this->connection); + my_id = this->connection->get_my_id(this->connection); + other_id = this->connection->get_other_id(this->connection); if (logger == NULL) { @@ -1029,9 +966,52 @@ static void log_status(private_ike_sa_t *this, logger_t *logger, char *name) } /** + * Implementation of public_ike_sa_t.delete. + */ +static status_t delete_(private_ike_sa_t *this) +{ + message_t *informational_request; + delete_payload_t *delete_payload; + u_int32_t timeout; + delete_half_open_ike_sa_job_t *job; + + if (get_state(this) != IKE_SA_ESTABLISHED) + { + this->logger->log(this->logger, ERROR, "Closing a not established IKE SA not allowed, aborting!"); + return INVALID_STATE; + } + + build_message(this, INFORMATIONAL, TRUE, &informational_request); + /* delete for the full IKE_SA, this deletes all child_sa's implicit */ + delete_payload = delete_payload_create(); + delete_payload->set_protocol_id(delete_payload, PROTO_IKE); + + informational_request->add_payload(informational_request, (payload_t*)delete_payload); + + if (send_request(this, informational_request) != SUCCESS) + { + /* send failed, but we ignore this, SA will get deleted anyway later */ + informational_request->destroy(informational_request); + } + + /* transit to state delete_requested */ + this->current_state->destroy(this->current_state); + set_new_state(this, (state_t*)delete_requested_create(this)); + + /* there is no guarantee that the other peer will acknowledge the delete, + * so we have to set a timeout where we destroy the SA... This is done with + * the delete_half_open_ike_sa_job as used in IKE SA setup. + */ + timeout = charon->configuration->get_half_open_ike_sa_timeout(charon->configuration); + job = delete_half_open_ike_sa_job_create(this->ike_sa_id); + charon->event_queue->add_relative(charon->event_queue, (job_t*)job, timeout); + return SUCCESS; +} + +/** * Implementation of protected_ike_sa_t.destroy. */ -static void destroy (private_ike_sa_t *this) +static void destroy(private_ike_sa_t *this) { child_sa_t *child_sa; @@ -1039,9 +1019,12 @@ static void destroy (private_ike_sa_t *this) this->ike_sa_id->get_initiator_spi(this->ike_sa_id), this->ike_sa_id->get_responder_spi(this->ike_sa_id), this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder"); + + if (get_state(this) == IKE_SA_ESTABLISHED) + { + this->logger->log(this->logger, ERROR, "Destroying an established IKE SA without knowledge from remote peer!"); + } - /* inform other peer of delete */ - send_delete_ike_sa_request(this); while (this->child_sas->remove_last(this->child_sas, (void**)&child_sa) == SUCCESS) { child_sa->destroy(child_sa); @@ -1127,8 +1110,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->protected.public.get_connection = (connection_t*(*)(ike_sa_t*)) get_connection; this->protected.public.retransmit_request = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit_request; this->protected.public.get_state = (ike_sa_state_t (*) (ike_sa_t *this)) get_state; - this->protected.public.send_delete_ike_sa_request = (void (*)(ike_sa_t*)) send_delete_ike_sa_request; this->protected.public.log_status = (void (*) (ike_sa_t*,logger_t*,char*))log_status; + this->protected.public.delete = (status_t(*)(ike_sa_t*))delete_; this->protected.public.destroy = (void(*)(ike_sa_t*))destroy; /* protected functions */ @@ -1158,9 +1141,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->protected.set_last_replied_message_id = (void (*) (protected_ike_sa_t *,u_int32_t)) set_last_replied_message_id; - /* private functions */ - this->resend_last_reply = resend_last_reply; - /* initialize private fields */ this->logger = logger_manager->get_logger(logger_manager, IKE_SA); |