aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/sa/ike_sa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ike_sa.c')
-rw-r--r--src/libcharon/sa/ike_sa.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 04e3d9ebd..b012c3d39 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -50,6 +50,7 @@
#include <processing/jobs/send_dpd_job.h>
#include <processing/jobs/send_keepalive_job.h>
#include <processing/jobs/rekey_ike_sa_job.h>
+#include <encoding/payloads/unknown_payload.h>
#ifdef ME
#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
*/
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;
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_request(response, FALSE);
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))
{
this->my_host->destroy(this->my_host);
@@ -1175,6 +1176,7 @@ METHOD(ike_sa_t, process_message, status_t,
{
status_t status;
bool is_request;
+ u_int8_t type = 0;
if (this->state == IKE_PASSIVE)
{ /* do not handle messages in passive state */
@@ -1185,9 +1187,29 @@ METHOD(ike_sa_t, process_message, status_t,
status = message->parse_body(message,
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 (is_request)
{
switch (status)
@@ -1196,21 +1218,28 @@ METHOD(ike_sa_t, process_message, status_t,
DBG1(DBG_IKE, "critical unknown payloads found");
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;
case PARSE_ERROR:
DBG1(DBG_IKE, "message parsing failed");
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;
case VERIFY_ERROR:
DBG1(DBG_IKE, "message verification failed");
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;
case FAILED:
@@ -1219,10 +1248,6 @@ METHOD(ike_sa_t, process_message, status_t,
break;
case INVALID_STATE:
DBG1(DBG_IKE, "found encrypted message, but no keys available");
- if (is_request)
- {
- send_notify_response(this, message, INVALID_SYNTAX);
- }
default:
break;
}
@@ -1252,7 +1277,8 @@ METHOD(ike_sa_t, process_message, status_t,
/* no config found for these hosts, destroy */
DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
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;
}
/* add a timeout if peer does not establish it completely */