diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index b63264bf9..0a808ac02 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -574,6 +574,7 @@ static payload_order_t aggressive_r_order[] = { */ static payload_rule_t informational_i_rules_v1[] = { /* payload type min max encr suff */ + {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, {DELETE_V1, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE}, {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, @@ -1946,22 +1947,25 @@ METHOD(message_t, parse_body, status_t, { hash_payload_t *hash_payload; chunk_t other_hash; - if (this->first_payload != HASH_V1) + if ((this->first_payload != HASH_V1) && (this->public.get_exchange_type(&this->public) != INFORMATIONAL_V1)) { DBG1(DBG_ENC, "expected HASH payload as first payload"); chunk_free(&hash); return VERIFY_ERROR; } - hash_payload = (hash_payload_t*)get_payload(this, HASH_V1); - other_hash = hash_payload->get_hash(hash_payload); - if (!chunk_equals(hash, other_hash)) + if (this->first_payload == HASH_V1) { - DBG1(DBG_ENC, "our hash does not match received %B", - &other_hash); - chunk_free(&hash); - return FAILED; + hash_payload = (hash_payload_t*)get_payload(this, HASH_V1); + other_hash = hash_payload->get_hash(hash_payload); + if (!chunk_equals(hash, other_hash)) + { + DBG1(DBG_ENC, "our hash does not match received %B", + &other_hash); + chunk_free(&hash); + return FAILED; + } + DBG2(DBG_ENC, "verified IKEv1 message with hash %B", &hash); } - DBG2(DBG_ENC, "verified IKEv1 message with hash %B", &hash); chunk_free(&hash); } } diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c index a5ffb0693..a72a0f37e 100644 --- a/src/libcharon/encoding/payloads/notify_payload.c +++ b/src/libcharon/encoding/payloads/notify_payload.c @@ -413,7 +413,7 @@ METHOD(payload_t, verify, status_t, case INVALID_MAJOR_VERSION: case NO_PROPOSAL_CHOSEN: { - if (this->notify_data.len != 0) + if ((this->notify_data.len != 0) && (this->type == NOTIFY)) { bad_length = TRUE; } diff --git a/src/libcharon/sa/task_manager_v1.c b/src/libcharon/sa/task_manager_v1.c index a2b172570..86b25e456 100644 --- a/src/libcharon/sa/task_manager_v1.c +++ b/src/libcharon/sa/task_manager_v1.c @@ -489,6 +489,8 @@ static status_t process_request(private_task_manager_t *this, enumerator_t *enumerator; task_t *task = NULL; bool send_response = FALSE; + payload_t *payload; + notify_payload_t *notify; if (this->passive_tasks->get_count(this->passive_tasks) == 0) { /* create tasks depending on request type, if not already some queued */ @@ -511,8 +513,44 @@ static status_t process_request(private_task_manager_t *this, this->passive_tasks->insert_last(this->passive_tasks, task); break; case INFORMATIONAL_V1: - /* TODO-IKEv1: informational */ - return FAILED; + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + switch (payload->get_type(payload)) + { + case NOTIFY_V1: + { + notify = (notify_payload_t*)payload; + switch (notify->get_notify_type(notify)) + { + /* TODO-IKEv1: Add notification types here as needed */ + case INITIAL_CONTACT_IKEV1: + break; + default: + if(notify->get_notify_type(notify) < 16384) + { + DBG1(DBG_IKE, "Received %N error notification.", notify_type_names, notify->get_notify_type(notify)); + return FAILED; + } + break; + } + break; + } + case DELETE_V1: + { + /* TODO-IKEv1: Delete payload handling. */ + break; + } + default: + break; + } + if (task) + { + break; + } + } + enumerator->destroy(enumerator); + break; case TRANSACTION: task = (task_t *)xauth_request_create(this->ike_sa, FALSE); this->passive_tasks->insert_last(this->passive_tasks, task); diff --git a/src/libcharon/sa/tasks/quick_mode.c b/src/libcharon/sa/tasks/quick_mode.c index 472aad8c6..10e0c224c 100644 --- a/src/libcharon/sa/tasks/quick_mode.c +++ b/src/libcharon/sa/tasks/quick_mode.c @@ -22,6 +22,7 @@ #include #include #include +#include typedef struct private_quick_mode_t private_quick_mode_t; @@ -548,9 +549,24 @@ METHOD(task_t, build_i, status_t, } } +status_t process_notify(notify_payload_t *notify) +{ + if(notify->get_notify_type(notify) < 16384) + { + DBG1(DBG_IKE, "Received %N error notification.", notify_type_names, notify->get_notify_type(notify)); + return FAILED; + } + DBG1(DBG_IKE, "Received %N notification.", notify_type_names, notify->get_notify_type(notify)); + return SUCCESS; +} + METHOD(task_t, process_r, status_t, private_quick_mode_t *this, message_t *message) { + enumerator_t *enumerator; + payload_t *payload; + status_t status; + switch (this->state) { case QM_INIT: @@ -625,6 +641,19 @@ METHOD(task_t, process_r, status_t, } case QM_NEGOTIATED: { + enumerator = message->create_payload_enumerator(message); + while(enumerator->enumerate(enumerator, &payload)) + { + if(payload->get_type(payload) == NOTIFY_V1) + { + status = process_notify((notify_payload_t *)payload); + if(status != SUCCESS) + { + return status; + } + } + } + enumerator->destroy(enumerator); if (!install(this)) { return FAILED;