diff --git a/src/charon/doc/Todo-list.txt b/src/charon/doc/Todo-list.txt index 7bff26d84..2398acc57 100644 --- a/src/charon/doc/Todo-list.txt +++ b/src/charon/doc/Todo-list.txt @@ -39,19 +39,19 @@ - certificate exchange + Apply -W's from Makefile.program to charon -- do ipsec status via starter ++ do ipsec status via starter - add more output to to up/down, somehow... -- stroke status should show configured connections -- stroke loglevel update ++ stroke status should show configured connections ++ stroke loglevel update - stroke argument parsing via getopts/gperf? - implement 3DES to load encrypted pem files -- ipsec.secrets parsing ++ ipsec.secrets parsing - trapping -- delete notify, when to send? ++ proper delete messages - notifys on connection setup failure - create child sa message/rekeying -- new build environment (autotools?) ++ new build environment (autotools?) diff --git a/src/charon/encoding/payloads/notify_payload.c b/src/charon/encoding/payloads/notify_payload.c index 43d0c5322..a4062cf42 100644 --- a/src/charon/encoding/payloads/notify_payload.c +++ b/src/charon/encoding/payloads/notify_payload.c @@ -44,7 +44,7 @@ mapping_t notify_message_type_m[] = { {NO_ADDITIONAL_SAS, "NO_ADDITIONAL_SAS"}, {INTERNAL_ADDRESS_FAILURE, "INTERNAL_ADDRESS_FAILURE"}, {FAILED_CP_REQUIRED, "FAILED_CP_REQUIRED"}, - {TS_UACCEPTABLE, "TS_UACCEPTABLE"}, + {TS_UNACCEPTABLE, "TS_UNACCEPTABLE"}, {INVALID_SELECTORS, "INVALID_SELECTORS"}, {INITIAL_CONTACT, "INITIAL_CONTACT"}, {SET_WINDOW_SIZE, "SET_WINDOW_SIZE"}, diff --git a/src/charon/encoding/payloads/notify_payload.h b/src/charon/encoding/payloads/notify_payload.h index 4c9383e49..ab86a6d53 100644 --- a/src/charon/encoding/payloads/notify_payload.h +++ b/src/charon/encoding/payloads/notify_payload.h @@ -60,7 +60,7 @@ enum notify_message_type_t { NO_ADDITIONAL_SAS = 35, INTERNAL_ADDRESS_FAILURE = 36, FAILED_CP_REQUIRED = 37, - TS_UACCEPTABLE = 38, + TS_UNACCEPTABLE = 38, INVALID_SELECTORS = 39, INITIAL_CONTACT = 16384, diff --git a/src/charon/encoding/payloads/sa_payload.c b/src/charon/encoding/payloads/sa_payload.c index 81b4e6709..345264b4d 100644 --- a/src/charon/encoding/payloads/sa_payload.c +++ b/src/charon/encoding/payloads/sa_payload.c @@ -341,6 +341,7 @@ sa_payload_t *sa_payload_create() /* public functions */ this->public.create_proposal_substructure_iterator = (iterator_t* (*) (sa_payload_t *,bool)) create_proposal_substructure_iterator; this->public.add_proposal_substructure = (void (*) (sa_payload_t *,proposal_substructure_t *)) add_proposal_substructure; + this->public.add_proposal = (void (*) (sa_payload_t*,proposal_t*))add_proposal; this->public.get_proposals = (linked_list_t* (*) (sa_payload_t *)) get_proposals; this->public.destroy = (void (*) (sa_payload_t *)) destroy; diff --git a/src/charon/sa/states/ike_auth_requested.c b/src/charon/sa/states/ike_auth_requested.c index 069f16506..45e40bed4 100644 --- a/src/charon/sa/states/ike_auth_requested.c +++ b/src/charon/sa/states/ike_auth_requested.c @@ -521,19 +521,33 @@ static status_t process_notify_payload(private_ike_auth_requested_t *this, notif case INVALID_SYNTAX: { this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an INVALID_SYNTAX notify. Deleting IKE_SA"); - return DESTROY_ME; + return DESTROY_ME; } case AUTHENTICATION_FAILED: { this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an AUTHENTICATION_FAILED notify. Deleting IKE_SA"); - return DESTROY_ME; + return DESTROY_ME; } case SINGLE_PAIR_REQUIRED: { this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a SINGLE_PAIR_REQUIRED notify. Deleting IKE_SA"); - return DESTROY_ME; + return DESTROY_ME; + } + case TS_UNACCEPTABLE: + { + /* TODO: We currently check only the replied TS payloads, which should be empty. Should + * we interpret the notify additionaly? */ + this->logger->log(this->logger, CONTROL, "IKE_AUTH reply contained a TS_UNACCEPTABLE notify. Ignored"); + return SUCCESS; + } + case NO_PROPOSAL_CHOSEN: + { + /* TODO: We currently check only the replied SA payload, which should be empty. Should + * we interpret the notify additionaly? */ + this->logger->log(this->logger, CONTROL, "IKE_AUTH reply contained a NO_PROPOSAL_CHOSEN notify. Ignored"); + return SUCCESS; } default: { diff --git a/src/charon/sa/states/ike_sa_init_responded.c b/src/charon/sa/states/ike_sa_init_responded.c index 3a379247c..249f05823 100644 --- a/src/charon/sa/states/ike_sa_init_responded.c +++ b/src/charon/sa/states/ike_sa_init_responded.c @@ -436,19 +436,11 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo status_t status; connection_t *connection; - /* get proposals from request */ + /* prepare reply */ + sa_response = sa_payload_create(); + + /* get proposals from request, and select one with ours */ proposal_list = request->get_proposals(request); - if (proposal_list->get_count(proposal_list) == 0) - { - /* if the other side did not offer any proposals, we do not create child sa's */ - this->logger->log(this->logger, AUDIT, "IKE_AUH request did not contain any proposals. No CHILD_SA created"); - sa_response = sa_payload_create(); - response->add_payload(response, (payload_t*)sa_response); - proposal_list->destroy(proposal_list); - return SUCCESS; - } - - /* now select a proposal */ this->logger->log(this->logger, CONTROL|LEVEL1, "Selecting proposals:"); proposal = this->policy->select_proposal(this->policy, proposal_list); /* list is not needed anymore */ @@ -457,37 +449,45 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo proposal_tmp->destroy(proposal_tmp); } proposal_list->destroy(proposal_list); - /* do we have a proposal */ + /* do we have a proposal? */ if (proposal == NULL) { - this->logger->log(this->logger, AUDIT, "IKE_AUTH request did not contain any proposals we accept. Deleting IKE_SA"); - this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER); - return DESTROY_ME; + notify_payload_t *notify; + this->logger->log(this->logger, AUDIT, "IKE_AUTH request did not contain any proposals we accept. " + "Adding NO_PROPOSAL_CHOSEN notify"); + /* add NO_PROPOSAL_CHOSEN and an empty SA payload */ + notify = notify_payload_create_from_protocol_and_type(PROTO_IKE, NO_PROPOSAL_CHOSEN); + response->add_payload(response, (payload_t*)notify); } - - /* set up child sa */ - seed = chunk_alloc(this->received_nonce.len + this->sent_nonce.len); - memcpy(seed.ptr, this->received_nonce.ptr, this->received_nonce.len); - memcpy(seed.ptr + this->received_nonce.len, this->sent_nonce.ptr, this->sent_nonce.len); - prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); - chunk_free(&seed); - - connection = this->ike_sa->get_connection(this->ike_sa); - this->child_sa = child_sa_create(connection->get_my_host(connection), - connection->get_other_host(connection)); - - status = this->child_sa->add(this->child_sa, proposal, prf_plus); - prf_plus->destroy(prf_plus); - if (status != SUCCESS) + else { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); - return DESTROY_ME; + /* set up child sa */ + seed = chunk_alloc(this->received_nonce.len + this->sent_nonce.len); + memcpy(seed.ptr, this->received_nonce.ptr, this->received_nonce.len); + memcpy(seed.ptr + this->received_nonce.len, this->sent_nonce.ptr, this->sent_nonce.len); + prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); + chunk_free(&seed); + + connection = this->ike_sa->get_connection(this->ike_sa); + this->child_sa = child_sa_create(connection->get_my_host(connection), + connection->get_other_host(connection)); + + status = this->child_sa->add(this->child_sa, proposal, prf_plus); + prf_plus->destroy(prf_plus); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); + /* TODO: how do we handle this cleanly? */ + sa_response->destroy(sa_response); + proposal->destroy(proposal); + return DESTROY_ME; + } + + /* add proposal to sa payload */ + sa_response->add_proposal(sa_response, proposal); + proposal->destroy(proposal); } - - /* create payload with selected propsal */ - sa_response = sa_payload_create_from_proposal(proposal); response->add_payload(response, (payload_t*)sa_response); - proposal->destroy(proposal); return SUCCESS; } @@ -550,6 +550,19 @@ static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_ ts_response = ts_payload_create_from_traffic_selectors(ts_initiator, ts_selected); response->add_payload(response, (payload_t*)ts_response); + /* add notify if traffic selectors do not match */ + if (!ts_initiator && + (ts_selected->get_count(ts_selected) == 0 || this->other_ts->get_count(this->other_ts) == 0)) + { + notify_payload_t *notify; + + this->logger->log(this->logger, AUDIT, "IKE_AUTH request did not contain any traffic selectors we accept. " + "Adding TS_UNACCEPTABLE notify"); + + notify = notify_payload_create_from_protocol_and_type(0, TS_UNACCEPTABLE); + response->add_payload(response, (payload_t*)notify); + } + /* cleanup */ while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS) { diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c index 9d9fb36b3..b8e5ba9a6 100755 --- a/src/charon/threads/stroke_interface.c +++ b/src/charon/threads/stroke_interface.c @@ -332,6 +332,8 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg) /* only initiate if it is an IKEv2 connection, ignore IKEv1 */ else if (connection->is_ikev2(connection)) { + this->stroke_logger->log(this->stroke_logger, CONTROL, "initiating connection \"%s\" (see log)...", msg->initiate.name); + job = initiate_ike_sa_job_create(connection); charon->job_queue->add(charon->job_queue, (job_t*)job); }