Move critical bit checking to ike_sa, notify payload includes unsupported payload type

This commit is contained in:
Martin Willi
2011-01-05 16:45:44 +01:00
parent e7099aa24e
commit c67de660d2
5 changed files with 62 additions and 26 deletions
+1 -13
View File
@@ -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",
-2
View File
@@ -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
View File
@@ -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 */
+14
View File
@@ -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,
+10
View File
@@ -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.
* *