diff options
author | Jan Hutter <jhutter@hsr.ch> | 2005-12-12 14:14:52 +0000 |
---|---|---|
committer | Jan Hutter <jhutter@hsr.ch> | 2005-12-12 14:14:52 +0000 |
commit | e9c0ca15e177d4651dca5092b02a50bfb57842a1 (patch) | |
tree | 7eedb7bb4c463cd19de516c7a3bddf72dfc5ec05 /Source/charon | |
parent | 6db4e80b569137103b5003b9585e32c12af1a694 (diff) | |
download | strongswan-e9c0ca15e177d4651dca5092b02a50bfb57842a1.tar.bz2 strongswan-e9c0ca15e177d4651dca5092b02a50bfb57842a1.tar.xz |
- added deletion of IKE_SA
Diffstat (limited to 'Source/charon')
-rw-r--r-- | Source/charon/config/configuration_manager.c | 12 | ||||
-rw-r--r-- | Source/charon/encoding/message.c | 46 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa.c | 34 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa.h | 9 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_auth_requested.c | 8 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_sa_established.c | 182 | ||||
-rw-r--r-- | Source/charon/threads/thread_pool.c | 5 |
7 files changed, 267 insertions, 29 deletions
diff --git a/Source/charon/config/configuration_manager.c b/Source/charon/config/configuration_manager.c index f2c726da5..4e9cdc5b4 100644 --- a/Source/charon/config/configuration_manager.c +++ b/Source/charon/config/configuration_manager.c @@ -745,15 +745,19 @@ static status_t get_rsa_private_key(private_configuration_manager_t *this, ident */ static status_t get_retransmit_timeout (private_configuration_manager_t *this, u_int32_t retransmit_count, u_int32_t *timeout) { + int new_timeout = this->first_retransmit_timeout, i; if ((retransmit_count > this->max_retransmit_count) && (this->max_retransmit_count != 0)) { return FAILED; } - /** - * TODO implement a good retransmit policy - */ - *timeout = this->first_retransmit_timeout * (retransmit_count + 1); + + for (i = 0; i < retransmit_count; i++) + { + new_timeout *= 2; + } + + *timeout = new_timeout; return SUCCESS; } diff --git a/Source/charon/encoding/message.c b/Source/charon/encoding/message.c index b67f06dd7..2aedf8492 100644 --- a/Source/charon/encoding/message.c +++ b/Source/charon/encoding/message.c @@ -165,6 +165,27 @@ static payload_rule_t ike_auth_r_payload_rules[] = { {CONFIGURATION,0,1,TRUE,FALSE}, }; + +/** + * Message rule for INFORMATIONAL from initiator. + */ +static payload_rule_t informational_i_payload_rules[] = { + {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, + {CONFIGURATION,0,1,TRUE,FALSE}, + {DELETE,0,1,TRUE,FALSE}, + +}; + +/** + * Message rule for INFORMATIONAL from responder. + */ +static payload_rule_t informational_r_payload_rules[] = { + {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, + {CONFIGURATION,0,1,TRUE,FALSE}, + {DELETE,0,1,TRUE,FALSE}, +}; + + /** * Message rules, defines allowed payloads. */ @@ -172,7 +193,9 @@ static message_rule_t message_rules[] = { {IKE_SA_INIT,TRUE,FALSE,(sizeof(ike_sa_init_i_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_i_payload_rules}, {IKE_SA_INIT,FALSE,FALSE,(sizeof(ike_sa_init_r_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_r_payload_rules}, {IKE_AUTH,TRUE,TRUE,(sizeof(ike_auth_i_payload_rules)/sizeof(payload_rule_t)),ike_auth_i_payload_rules}, - {IKE_AUTH,FALSE,TRUE,(sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),ike_auth_r_payload_rules} + {IKE_AUTH,FALSE,TRUE,(sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),ike_auth_r_payload_rules}, + {INFORMATIONAL,TRUE,TRUE,(sizeof(informational_i_payload_rules)/sizeof(payload_rule_t)),informational_i_payload_rules}, + {INFORMATIONAL,FALSE,TRUE,(sizeof(informational_r_payload_rules)/sizeof(payload_rule_t)),informational_r_payload_rules} }; @@ -1042,6 +1065,8 @@ static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, si this->payloads->remove_first(this->payloads,¤t_payload); all_payloads->insert_last(all_payloads,current_payload); } + + encryption_payload = encryption_payload_create(); this->logger->log(this->logger, CONTROL | LEVEL2, "Check each payloads if they have to get encrypted"); while (all_payloads->get_count(all_payloads) > 0) @@ -1072,10 +1097,6 @@ static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, si if (to_encrypt) { - if (encryption_payload == NULL) - { - encryption_payload = encryption_payload_create(); - } this->logger->log(this->logger, CONTROL | LEVEL2, "Insert payload %s to encryption payload", mapping_find(payload_type_m,current_payload->get_type(current_payload))); @@ -1090,15 +1111,12 @@ static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, si } status = SUCCESS; - if (encryption_payload != NULL) - { - this->logger->log(this->logger, CONTROL | LEVEL2, "Set transforms for encryption payload "); - encryption_payload->set_transforms(encryption_payload,crypter,signer); - this->logger->log(this->logger, CONTROL | LEVEL1, "Encrypt all payloads of encrypted payload"); - status = encryption_payload->encrypt(encryption_payload); - this->logger->log(this->logger, CONTROL | LEVEL2, "Add encrypted payload to payload list"); - this->public.add_payload(&(this->public), (payload_t*)encryption_payload); - } + this->logger->log(this->logger, CONTROL | LEVEL2, "Set transforms for encryption payload "); + encryption_payload->set_transforms(encryption_payload,crypter,signer); + this->logger->log(this->logger, CONTROL | LEVEL1, "Encrypt all payloads of encrypted payload"); + status = encryption_payload->encrypt(encryption_payload); + this->logger->log(this->logger, CONTROL | LEVEL2, "Add encrypted payload to payload list"); + this->public.add_payload(&(this->public), (payload_t*)encryption_payload); all_payloads->destroy(all_payloads); diff --git a/Source/charon/sa/ike_sa.c b/Source/charon/sa/ike_sa.c index d87ebe0c6..bae5ea70c 100644 --- a/Source/charon/sa/ike_sa.c +++ b/Source/charon/sa/ike_sa.c @@ -35,6 +35,7 @@ #include <encoding/payloads/sa_payload.h> #include <encoding/payloads/nonce_payload.h> #include <encoding/payloads/ke_payload.h> +#include <encoding/payloads/delete_payload.h> #include <encoding/payloads/transform_substructure.h> #include <encoding/payloads/transform_attribute.h> #include <sa/states/initiator_init.h> @@ -374,6 +375,36 @@ static status_t initialize_connection(private_ike_sa_t *this, char *name) } /** + * 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; + 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,IKE); + + informational_request->add_payload(informational_request,(payload_t *)delete_payload); + + status = this->protected.send_request(&(this->protected), informational_request); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Unable to send INFORMATIONAL DELETE request"); + informational_request->destroy(informational_request); + } +} + +/** * Implementation of protected_ike_sa_t.get_id. */ static ike_sa_id_t* get_id(private_ike_sa_t *this) @@ -868,7 +899,7 @@ static void send_notify(private_ike_sa_t *this, exchange_type_t exchange_type, n response->add_payload(response,(payload_t *) payload); /* generate packet */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Gnerate packet from message"); + this->logger->log(this->logger, CONTROL|LEVEL2, "Generate packet from message"); status = response->generate(response, this->crypter_responder, this->signer_responder, &packet); if (status != SUCCESS) { @@ -1069,6 +1100,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->protected.public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id; 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.destroy = (void(*)(ike_sa_t*))destroy; /* protected functions */ diff --git a/Source/charon/sa/ike_sa.h b/Source/charon/sa/ike_sa.h index 92da57cfd..25338363d 100644 --- a/Source/charon/sa/ike_sa.h +++ b/Source/charon/sa/ike_sa.h @@ -95,6 +95,15 @@ struct ike_sa_t { * - NOT_FOUND if request doesn't have to be retransmited */ status_t (*retransmit_request) (ike_sa_t *this, u_int32_t message_id); + + /** + * @brief Sends a request to delete IKE_SA. + * + * Only supported in state IKE_SA_ESTABLISHED + * + * @param this calling object + */ + void (*send_delete_ike_sa_request) (ike_sa_t *this); /** * @brief Get the id of the SA. diff --git a/Source/charon/sa/states/ike_auth_requested.c b/Source/charon/sa/states/ike_auth_requested.c index f2385fe4c..13d980b57 100644 --- a/Source/charon/sa/states/ike_auth_requested.c +++ b/Source/charon/sa/states/ike_auth_requested.c @@ -127,11 +127,11 @@ struct private_ike_auth_requested_t { /** * Process a notify payload * - * @param this calling object - * @param ts_initiator TRUE if TS payload is TSi, FALSE for TSr - * @param ts_payload TS payload of responder + * @param this calling object + * @param notify_payload notify payload * * - SUCCESS + * - FAILED * - DELETE_ME */ status_t (*process_notify_payload) (private_ike_auth_requested_t *this, notify_payload_t *notify_payload); @@ -174,7 +174,7 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i status = ike_auth_reply->parse_body(ike_auth_reply, crypter, signer); if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply decryption faild. Ignoring message"); + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply decryption failed. Ignoring message"); return status; } diff --git a/Source/charon/sa/states/ike_sa_established.c b/Source/charon/sa/states/ike_sa_established.c index 99e9a7291..b020fc995 100644 --- a/Source/charon/sa/states/ike_sa_established.c +++ b/Source/charon/sa/states/ike_sa_established.c @@ -23,6 +23,7 @@ #include "ike_sa_established.h" #include <utils/allocator.h> +#include <encoding/payloads/delete_payload.h> typedef struct private_ike_sa_established_t private_ike_sa_established_t; @@ -37,10 +38,36 @@ struct private_ike_sa_established_t { ike_sa_established_t public; /** - * Assigned IKE_SA + * Assigned IKE_SA. */ protected_ike_sa_t *ike_sa; + /** + * Assigned logger. Use logger of IKE_SA. + */ + logger_t *logger; + + /** + * Process received DELETE payload and build DELETE payload for INFORMATIONAL response. + * + * @param this calling object + * @param request DELETE payload received in INFORMATIONAL request + * @param response The created DELETE payload is added to this message_t object + */ + status_t (*build_delete_payload) (private_ike_sa_established_t *this, delete_payload_t *request, message_t *response); + + /** + * Process a notify payload + * + * @param this calling object + * @param notify_payload notify payload + * @param response response message of type INFORMATIONAL + * + * - SUCCESS + * - FAILED + * - DELETE_ME + */ + status_t (*process_notify_payload) (private_ike_sa_established_t *this, notify_payload_t *notify_payload,message_t *response); }; /** @@ -48,11 +75,155 @@ struct private_ike_sa_established_t { */ static status_t process_message(private_ike_sa_established_t *this, message_t *message) { + delete_payload_t *delete_request = NULL; + iterator_t *payloads; + message_t *response; + crypter_t *crypter; + signer_t *signer; + status_t status; + + if (message->get_exchange_type(message) != INFORMATIONAL) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_established", + mapping_find(exchange_type_m,message->get_exchange_type(message))); + return FAILED; + } + + if (!message->get_request(message)) + { + this->logger->log(this->logger, ERROR | LEVEL1, "INFORMATIONAL responses not handled in state ike_sa_established"); + return FAILED; + } + + /* get signer for verification and crypter for decryption */ + signer = this->ike_sa->get_signer_responder(this->ike_sa); + crypter = this->ike_sa->get_crypter_responder(this->ike_sa); + + /* parse incoming message */ + status = message->parse_body(message, crypter, signer); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "INFORMATIONAL request decryption failed. Ignoring message"); + return status; + } + + /* build empty INFORMATIONAL message */ + this->ike_sa->build_message(this->ike_sa, INFORMATIONAL, FALSE, &response); + + payloads = message->get_payload_iterator(message); + + while (payloads->has_next(payloads)) + { + payload_t *payload; + payloads->current(payloads, (void**)&payload); + + switch (payload->get_type(payload)) + { + case NOTIFY: + { + notify_payload_t *notify_payload = (notify_payload_t *) payload; + /* handle the notify directly, abort if no further processing required */ + status = this->process_notify_payload(this, notify_payload,response); + if (status != SUCCESS) + { + payloads->destroy(payloads); + response->destroy(response); + return status; + } + } + case DELETE: + { + delete_request = (delete_payload_t *) payload; + } + default: + { + this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)", + mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); + break; + } + } + } + /* iterator can be destroyed */ + payloads->destroy(payloads); + + if (delete_request) + { + status = this->build_delete_payload(this, delete_request, response); + if (status == DELETE_ME) + { + status = this->ike_sa->send_response(this->ike_sa, response); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Unable to send INFORMATIONAL reply"); + response->destroy(response); + return FAILED; + } + response->destroy(response); + return status; + } + } + + + status = this->ike_sa->send_response(this->ike_sa, response); + /* message can now be sent (must not be destroyed) */ + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Unable to send INFORMATIONAL reply"); + response->destroy(response); + return FAILED; + } + + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_established_t.build_sa_payload; + */ +static status_t build_delete_payload (private_ike_sa_established_t *this, delete_payload_t *request, message_t *response_message) +{ + delete_payload_t *response; + if (request->get_protocol_id(request) == IKE) + { + this->logger->log(this->logger, AUDIT, "DELETE request for IKE_SA received. Create delete reply."); + + response = delete_payload_create(); + response->set_protocol_id(response,IKE); + + response_message->add_payload(response_message,(payload_t *)response); + /* IKE_SA has to get deleted */ + return DELETE_ME; + } + + this->logger->log(this->logger, AUDIT, "DELETE payload for CHILD_SAs not supported and handled."); + return SUCCESS; } /** - * Implements state_t.get_state + * Implementation of private_ike_sa_established_t.process_notify_payload; + */ +static status_t process_notify_payload (private_ike_sa_established_t *this, notify_payload_t *notify_payload, message_t *response) +{ + notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); + + this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s for protocol %s", + mapping_find(notify_message_type_m, notify_message_type), + mapping_find(protocol_id_m, notify_payload->get_protocol_id(notify_payload))); + + switch (notify_message_type) + { + default: + { + this->logger->log(this->logger, AUDIT, "INFORMATIONAL request contained an unknown notify (%d), ignored.", notify_message_type); + } + } + + + return SUCCESS; +} + +/** + * Implementation of state_t.get_state. */ static ike_sa_state_t get_state(private_ike_sa_established_t *this) { @@ -60,7 +231,7 @@ static ike_sa_state_t get_state(private_ike_sa_established_t *this) } /** - * Implements state_t.get_state + * Implementation of state_t.get_state */ static void destroy(private_ike_sa_established_t *this) { @@ -79,8 +250,13 @@ ike_sa_established_t *ike_sa_established_create(protected_ike_sa_t *ike_sa) this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; this->public.state_interface.destroy = (void (*) (state_t *)) destroy; + /* private functions */ + this->process_notify_payload = process_notify_payload; + this->build_delete_payload = build_delete_payload; + /* private data */ this->ike_sa = ike_sa; + this->logger = ike_sa->get_logger(ike_sa); return &(this->public); } diff --git a/Source/charon/threads/thread_pool.c b/Source/charon/threads/thread_pool.c index 2b0259e92..ac926a30b 100644 --- a/Source/charon/threads/thread_pool.c +++ b/Source/charon/threads/thread_pool.c @@ -444,9 +444,8 @@ static void process_delete_established_ike_sa_job(private_thread_pool_t *this, d } default: { - /* - * TODO Send delete notify - */ + this->worker_logger->log(this->worker_logger, CONTROL, "Send delete request for IKE_SA."); + ike_sa->send_delete_ike_sa_request(ike_sa); break; } } |