Move critical bit checking to ike_sa, notify payload includes unsupported payload type
This commit is contained in:
@@ -1313,21 +1313,9 @@ static status_t verify(private_message_t *this)
|
|||||||
while (enumerator->enumerate(enumerator, &payload))
|
while (enumerator->enumerate(enumerator, &payload))
|
||||||
{
|
{
|
||||||
payload_type_t type;
|
payload_type_t type;
|
||||||
unknown_payload_t *unknown;
|
|
||||||
|
|
||||||
type = payload->get_type(payload);
|
type = payload->get_type(payload);
|
||||||
if (!payload_is_known(type))
|
if (type == rule->type)
|
||||||
{
|
|
||||||
unknown = (unknown_payload_t*)payload;
|
|
||||||
if (unknown->is_critical(unknown))
|
|
||||||
{
|
|
||||||
DBG1(DBG_ENC, "payload type %N is not supported, "
|
|
||||||
"but its critical!", payload_type_names, type);
|
|
||||||
enumerator->destroy(enumerator);
|
|
||||||
return NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (type == rule->type)
|
|
||||||
{
|
{
|
||||||
found++;
|
found++;
|
||||||
DBG2(DBG_ENC, "found payload of type %N",
|
DBG2(DBG_ENC, "found payload of type %N",
|
||||||
|
|||||||
@@ -211,8 +211,6 @@ struct message_t {
|
|||||||
* @param aead aead transform to verify/decrypt message
|
* @param aead aead transform to verify/decrypt message
|
||||||
* @return
|
* @return
|
||||||
* - SUCCESS if parsing successful
|
* - SUCCESS if parsing successful
|
||||||
* - NOT_SUPPORTED if ciritcal unknown payloads found
|
|
||||||
* - NOT_SUPPORTED if message type is not supported!
|
|
||||||
* - PARSE_ERROR if message parsing failed
|
* - PARSE_ERROR if message parsing failed
|
||||||
* - VERIFY_ERROR if message verification failed (bad syntax)
|
* - VERIFY_ERROR if message verification failed (bad syntax)
|
||||||
* - FAILED if integrity check failed
|
* - FAILED if integrity check failed
|
||||||
|
|||||||
+37
-11
@@ -50,6 +50,7 @@
|
|||||||
#include <processing/jobs/send_dpd_job.h>
|
#include <processing/jobs/send_dpd_job.h>
|
||||||
#include <processing/jobs/send_keepalive_job.h>
|
#include <processing/jobs/send_keepalive_job.h>
|
||||||
#include <processing/jobs/rekey_ike_sa_job.h>
|
#include <processing/jobs/rekey_ike_sa_job.h>
|
||||||
|
#include <encoding/payloads/unknown_payload.h>
|
||||||
|
|
||||||
#ifdef ME
|
#ifdef ME
|
||||||
#include <sa/tasks/ike_me.h>
|
#include <sa/tasks/ike_me.h>
|
||||||
@@ -901,7 +902,7 @@ METHOD(ike_sa_t, generate_message, status_t,
|
|||||||
* send a notify back to the sender
|
* send a notify back to the sender
|
||||||
*/
|
*/
|
||||||
static void send_notify_response(private_ike_sa_t *this, message_t *request,
|
static void send_notify_response(private_ike_sa_t *this, message_t *request,
|
||||||
notify_type_t type)
|
notify_type_t type, chunk_t data)
|
||||||
{
|
{
|
||||||
message_t *response;
|
message_t *response;
|
||||||
packet_t *packet;
|
packet_t *packet;
|
||||||
@@ -910,7 +911,7 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request,
|
|||||||
response->set_exchange_type(response, request->get_exchange_type(request));
|
response->set_exchange_type(response, request->get_exchange_type(request));
|
||||||
response->set_request(response, FALSE);
|
response->set_request(response, FALSE);
|
||||||
response->set_message_id(response, request->get_message_id(request));
|
response->set_message_id(response, request->get_message_id(request));
|
||||||
response->add_notify(response, FALSE, type, chunk_empty);
|
response->add_notify(response, FALSE, type, data);
|
||||||
if (this->my_host->is_anyaddr(this->my_host))
|
if (this->my_host->is_anyaddr(this->my_host))
|
||||||
{
|
{
|
||||||
this->my_host->destroy(this->my_host);
|
this->my_host->destroy(this->my_host);
|
||||||
@@ -1175,6 +1176,7 @@ METHOD(ike_sa_t, process_message, status_t,
|
|||||||
{
|
{
|
||||||
status_t status;
|
status_t status;
|
||||||
bool is_request;
|
bool is_request;
|
||||||
|
u_int8_t type = 0;
|
||||||
|
|
||||||
if (this->state == IKE_PASSIVE)
|
if (this->state == IKE_PASSIVE)
|
||||||
{ /* do not handle messages in passive state */
|
{ /* do not handle messages in passive state */
|
||||||
@@ -1185,9 +1187,29 @@ METHOD(ike_sa_t, process_message, status_t,
|
|||||||
|
|
||||||
status = message->parse_body(message,
|
status = message->parse_body(message,
|
||||||
this->keymat->get_aead(this->keymat, TRUE));
|
this->keymat->get_aead(this->keymat, TRUE));
|
||||||
|
if (status == SUCCESS)
|
||||||
|
{ /* check for unsupported critical payloads */
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
unknown_payload_t *unknown;
|
||||||
|
payload_t *payload;
|
||||||
|
|
||||||
|
enumerator = message->create_payload_enumerator(message);
|
||||||
|
while (enumerator->enumerate(enumerator, &payload))
|
||||||
|
{
|
||||||
|
unknown = (unknown_payload_t*)payload;
|
||||||
|
type = payload->get_type(payload);
|
||||||
|
if (!payload_is_known(type) &&
|
||||||
|
unknown->is_critical(unknown))
|
||||||
|
{
|
||||||
|
DBG1(DBG_ENC, "payload type %N is not supported, "
|
||||||
|
"but its critical!", payload_type_names, type);
|
||||||
|
status = NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
}
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (is_request)
|
if (is_request)
|
||||||
{
|
{
|
||||||
switch (status)
|
switch (status)
|
||||||
@@ -1196,21 +1218,28 @@ METHOD(ike_sa_t, process_message, status_t,
|
|||||||
DBG1(DBG_IKE, "critical unknown payloads found");
|
DBG1(DBG_IKE, "critical unknown payloads found");
|
||||||
if (is_request)
|
if (is_request)
|
||||||
{
|
{
|
||||||
send_notify_response(this, message, UNSUPPORTED_CRITICAL_PAYLOAD);
|
send_notify_response(this, message,
|
||||||
|
UNSUPPORTED_CRITICAL_PAYLOAD,
|
||||||
|
chunk_from_thing(type));
|
||||||
|
this->task_manager->incr_mid(this->task_manager, FALSE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PARSE_ERROR:
|
case PARSE_ERROR:
|
||||||
DBG1(DBG_IKE, "message parsing failed");
|
DBG1(DBG_IKE, "message parsing failed");
|
||||||
if (is_request)
|
if (is_request)
|
||||||
{
|
{
|
||||||
send_notify_response(this, message, INVALID_SYNTAX);
|
send_notify_response(this, message,
|
||||||
|
INVALID_SYNTAX, chunk_empty);
|
||||||
|
this->task_manager->incr_mid(this->task_manager, FALSE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VERIFY_ERROR:
|
case VERIFY_ERROR:
|
||||||
DBG1(DBG_IKE, "message verification failed");
|
DBG1(DBG_IKE, "message verification failed");
|
||||||
if (is_request)
|
if (is_request)
|
||||||
{
|
{
|
||||||
send_notify_response(this, message, INVALID_SYNTAX);
|
send_notify_response(this, message,
|
||||||
|
INVALID_SYNTAX, chunk_empty);
|
||||||
|
this->task_manager->incr_mid(this->task_manager, FALSE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FAILED:
|
case FAILED:
|
||||||
@@ -1219,10 +1248,6 @@ METHOD(ike_sa_t, process_message, status_t,
|
|||||||
break;
|
break;
|
||||||
case INVALID_STATE:
|
case INVALID_STATE:
|
||||||
DBG1(DBG_IKE, "found encrypted message, but no keys available");
|
DBG1(DBG_IKE, "found encrypted message, but no keys available");
|
||||||
if (is_request)
|
|
||||||
{
|
|
||||||
send_notify_response(this, message, INVALID_SYNTAX);
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1252,7 +1277,8 @@ METHOD(ike_sa_t, process_message, status_t,
|
|||||||
/* no config found for these hosts, destroy */
|
/* no config found for these hosts, destroy */
|
||||||
DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
|
DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
|
||||||
me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
|
me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
|
||||||
send_notify_response(this, message, NO_PROPOSAL_CHOSEN);
|
send_notify_response(this, message,
|
||||||
|
NO_PROPOSAL_CHOSEN, chunk_empty);
|
||||||
return DESTROY_ME;
|
return DESTROY_ME;
|
||||||
}
|
}
|
||||||
/* add a timeout if peer does not establish it completely */
|
/* add a timeout if peer does not establish it completely */
|
||||||
|
|||||||
@@ -1008,6 +1008,19 @@ METHOD(task_manager_t, busy, bool,
|
|||||||
return (this->active_tasks->get_count(this->active_tasks) > 0);
|
return (this->active_tasks->get_count(this->active_tasks) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(task_manager_t, incr_mid, void,
|
||||||
|
private_task_manager_t *this, bool initiate)
|
||||||
|
{
|
||||||
|
if (initiate)
|
||||||
|
{
|
||||||
|
this->initiating.mid++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->responding.mid++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(task_manager_t, reset, void,
|
METHOD(task_manager_t, reset, void,
|
||||||
private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
|
private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
|
||||||
{
|
{
|
||||||
@@ -1091,6 +1104,7 @@ task_manager_t *task_manager_create(ike_sa_t *ike_sa)
|
|||||||
.queue_task = _queue_task,
|
.queue_task = _queue_task,
|
||||||
.initiate = _initiate,
|
.initiate = _initiate,
|
||||||
.retransmit = _retransmit,
|
.retransmit = _retransmit,
|
||||||
|
.incr_mid = _incr_mid,
|
||||||
.reset = _reset,
|
.reset = _reset,
|
||||||
.adopt_tasks = _adopt_tasks,
|
.adopt_tasks = _adopt_tasks,
|
||||||
.busy = _busy,
|
.busy = _busy,
|
||||||
|
|||||||
@@ -148,6 +148,16 @@ struct task_manager_t {
|
|||||||
*/
|
*/
|
||||||
void (*adopt_tasks) (task_manager_t *this, task_manager_t *other);
|
void (*adopt_tasks) (task_manager_t *this, task_manager_t *other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment a message ID counter, in- or outbound.
|
||||||
|
*
|
||||||
|
* If a message is processed outside of the manager, this call increments
|
||||||
|
* the message ID counters of the task manager.
|
||||||
|
*
|
||||||
|
* @param inititate TRUE to increment the initiating ID
|
||||||
|
*/
|
||||||
|
void (*incr_mid)(task_manager_t *this, bool initiate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset message ID counters of the task manager.
|
* Reset message ID counters of the task manager.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user