diff --git a/src/charon/doc/Todo-list.txt b/src/charon/doc/Todo-list.txt index 7bb46438b..b096faa82 100644 --- a/src/charon/doc/Todo-list.txt +++ b/src/charon/doc/Todo-list.txt @@ -60,11 +60,13 @@ Todo-List for charon + use dpdaction/dpddelay parameters from ipsec.conf / add firewall script support -- do not link unneeded libraries in bins -- include only a minimum of NATD payloads -- implement 3DES to load encrypted pem files -- implement a "event bus" mechanism - - add more output to to up/down, somehow... ++ do not link unneeded libraries in bins ++ include only a minimum of NATD payloads ++ implement 3DES to load encrypted pem files ++ implement a "event bus" mechanism + / add more output to to up/down, somehow... + - detach console after first keyingtry + - proper handling of CTRL+C console detach (SIG_PIPE) - configure flag which allows to ommit vendor id in pluto - ikelifetime should optionally enforce reauthentication - cookies/DDoS prevention @@ -74,7 +76,8 @@ Todo-List for charon - add support for CERTREQs - proper handling of multiple certificate payloads (import order) - add a Rekey-Counter for SAs in "statusall" -- ipsec status: - - on one line: ip, id, spi +- ipsec status: + + on one line: ip, id, spi - no key age, rekey for IKE - - byte count \ No newline at end of file + - byte count +- retry transaction on failure while keyingtries > 1 \ No newline at end of file diff --git a/src/charon/sa/transactions/delete_ike_sa.c b/src/charon/sa/transactions/delete_ike_sa.c index af1da3ab7..26817bb6a 100644 --- a/src/charon/sa/transactions/delete_ike_sa.c +++ b/src/charon/sa/transactions/delete_ike_sa.c @@ -56,6 +56,11 @@ struct private_delete_ike_sa_t { * Times we did send the request */ u_int32_t requested; + + /** + * is the IKE_SA redundant and gets deleted without further notification? + */ + bool redundant; }; /** @@ -92,6 +97,12 @@ static status_t get_request(private_delete_ike_sa_t *this, message_t **result) me = this->ike_sa->get_my_host(this->ike_sa); other = this->ike_sa->get_other_host(this->ike_sa); + this->redundant = this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING; + + if (!this->redundant) + { + SIG(IKE_DOWN_START, "deleting IKE_SA"); + } /* build the request */ request = message_create(); @@ -140,6 +151,12 @@ static status_t get_response(private_delete_ike_sa_t *this, message_t *request, me = this->ike_sa->get_my_host(this->ike_sa); other = this->ike_sa->get_other_host(this->ike_sa); this->message_id = request->get_message_id(request); + this->redundant = this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING; + + if (!this->redundant) + { + SIG(IKE_DOWN_START, "deleting IKE_SA"); + } /* set up response */ response = message_create(); @@ -155,7 +172,10 @@ static status_t get_response(private_delete_ike_sa_t *this, message_t *request, /* check message type */ if (request->get_exchange_type(request) != INFORMATIONAL) { - DBG1(DBG_IKE, "INFORMATIONAL response of invalid type, deleting IKE_SA"); + if (!this->redundant) + { + SIG(IKE_DOWN_FAILED, "INFORMATIONAL response of invalid type, deleting IKE_SA"); + } return DESTROY_ME; } @@ -197,6 +217,10 @@ static status_t get_response(private_delete_ike_sa_t *this, message_t *request, return SUCCESS; } this->ike_sa->set_state(this->ike_sa, IKE_DELETING); + if (!this->redundant) + { + SIG(IKE_DOWN_SUCCESS, "IKE_SA deleted on request"); + } return DESTROY_ME; } @@ -210,11 +234,18 @@ static status_t conclude(private_delete_ike_sa_t *this, message_t *response, /* check message type */ if (response->get_exchange_type(response) != INFORMATIONAL) { - DBG1(DBG_IKE, "INFORMATIONAL response of invalid type, deleting IKE_SA"); + if (!this->redundant) + { + SIG(IKE_DOWN_FAILED, "INFORMATIONAL response of invalid type, deleting IKE_SA"); + } return DESTROY_ME; } /* this is only an acknowledge. We can't do anything here, but delete * the IKE_SA. */ + if (!this->redundant) + { + SIG(IKE_DOWN_SUCCESS, "IKE_SA deleted"); + } return DESTROY_ME; } @@ -247,6 +278,7 @@ delete_ike_sa_t *delete_ike_sa_create(ike_sa_t *ike_sa) this->message_id = 0; this->message = NULL; this->requested = 0; + this->redundant = FALSE; return &this->public; } diff --git a/src/charon/sa/transactions/ike_auth.c b/src/charon/sa/transactions/ike_auth.c index ec54dd653..1bb2534d2 100644 --- a/src/charon/sa/transactions/ike_auth.c +++ b/src/charon/sa/transactions/ike_auth.c @@ -995,8 +995,14 @@ static void destroy(private_ike_auth_t *this) DESTROY_IF(this->child_sa); DESTROY_IF(this->policy); DESTROY_IF(this->connection); - this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy)); - this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy)); + if (this->tsi) + { + this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy)); + } + if (this->tsr) + { + this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy)); + } chunk_free(&this->nonce_i); chunk_free(&this->nonce_r); chunk_free(&this->init_request); diff --git a/src/charon/sa/transactions/rekey_ike_sa.c b/src/charon/sa/transactions/rekey_ike_sa.c index d2dfe01b6..59fc6f84b 100644 --- a/src/charon/sa/transactions/rekey_ike_sa.c +++ b/src/charon/sa/transactions/rekey_ike_sa.c @@ -757,9 +757,10 @@ static status_t conclude(private_rekey_ike_sa_t *this, message_t *response, if (switchto_new_sa(this, TRUE) != SUCCESS) { - /* this should not happen. But if, we destroy both SAs */ + /* this should not happen. But if, we destroy the new SAs */ + this->new_sa->set_state(this->new_sa, IKE_REKEYING); *next = (transaction_t*)delete_ike_sa_create(this->new_sa); - return DESTROY_ME; + return FAILED; } /* IKE_SA successfully created. If the other peer initiated rekeying @@ -800,7 +801,12 @@ static status_t conclude(private_rekey_ike_sa_t *this, message_t *response, /* the other has won, he gets our children */ other_trans->new_sa->adopt_children(other_trans->new_sa, this->ike_sa); /* we have lost simlutaneous rekeying, delete the SA we just have created */ - this->new_sa->delete(this->new_sa); + this->new_sa->set_state(this->new_sa, IKE_REKEYING); + *next = (transaction_t*)delete_ike_sa_create(this->new_sa); + } + else + { + other_trans->new_sa->set_state(other_trans->new_sa, IKE_REKEYING); } /* other trans' SA is still not checked in, so do it now. It's SA will get * deleted by remote peer. */ @@ -811,8 +817,8 @@ static status_t conclude(private_rekey_ike_sa_t *this, message_t *response, if (!this->lost) { /* we have won. delete old IKE_SA, and migrate all children */ - *next = (transaction_t*)delete_ike_sa_create(this->ike_sa); this->new_sa->adopt_children(this->new_sa, this->ike_sa); + *next = (transaction_t*)delete_ike_sa_create(this->ike_sa); } charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa); diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c index 62d71dd95..0163f18a2 100755 --- a/src/charon/threads/stroke_interface.c +++ b/src/charon/threads/stroke_interface.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "stroke_interface.h" @@ -507,7 +508,7 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg) connection->destroy(connection); return; } - + policy = charon->policies->get_policy_by_name(charon->policies, msg->initiate.name); if (policy == NULL) @@ -521,6 +522,14 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg) } job = initiate_job_create(connection, policy); + /* + if (msg->output_verbosity < 0) + { + TODO: detach immediately if verbosity is SILENT. Local credential store + is not threadsave yet, so this would cause crashes!! + charon->job_queue->add(charon->job_queue, (job_t*)job); + return; +}*/ charon->bus->set_listen_state(charon->bus, TRUE); charon->job_queue->add(charon->job_queue, (job_t*)job); @@ -541,11 +550,11 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg) fprintf(this->out, "\n") < 0 || fflush(this->out)) { + charon->bus->set_listen_state(charon->bus, FALSE); break; } } - /* TODO: Handle INVALID_KE_PAYLOAD signal (ike_sa switch) */ switch (signal) { case CHILD_UP_SUCCESS: @@ -885,6 +894,10 @@ static void stroke_receive(private_stroke_t *this) int strokefd; int oldstate; + /* ignore sigpipe. writing over the pipe back to the console + * only fails if SIGPIPE is ignored. */ + signal(SIGPIPE, SIG_IGN); + /* disable cancellation by default */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);