response->destroy(response);
}
+/**
+ * Send an INVALID_SYNTAX notify and destroy the IKE_SA for authenticated
+ * messages.
+ */
+static status_t send_invalid_syntax(private_task_manager_t *this,
+ message_t *msg)
+{
+ send_notify_response(this, msg, INVALID_SYNTAX, chunk_empty);
+ incr_mid(this, FALSE);
+
+ /* IKE_SA_INIT is currently the only type the parser accepts unprotected,
+ * don't destroy the IKE_SA if such a message is invalid */
+ if (msg->get_exchange_type(msg) == IKE_SA_INIT)
+ {
+ return FAILED;
+ }
+ return DESTROY_ME;
+}
+
/**
* Parse the given message and verify that it is valid.
*/
static status_t parse_message(private_task_manager_t *this, message_t *msg)
{
- status_t status;
+ status_t parse_status, status;
uint8_t type = 0;
- status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
+ parse_status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
- if (status == SUCCESS)
+ if (parse_status == SUCCESS)
{ /* check for unsupported critical payloads */
enumerator_t *enumerator;
unknown_payload_t *unknown;
{
type = unknown->get_type(unknown);
DBG1(DBG_ENC, "payload type %N is not supported, "
- "but its critical!", payload_type_names, type);
- status = NOT_SUPPORTED;
+ "but payload is critical!", payload_type_names, type);
+ parse_status = NOT_SUPPORTED;
break;
}
}
enumerator->destroy(enumerator);
}
- if (status != SUCCESS)
+ status = parse_status;
+
+ if (parse_status != SUCCESS)
{
bool is_request = msg->get_request(msg);
- switch (status)
+ switch (parse_status)
{
case NOT_SUPPORTED:
DBG1(DBG_IKE, "critical unknown payloads found");
DBG1(DBG_IKE, "message parsing failed");
if (is_request)
{
- send_notify_response(this, msg,
- INVALID_SYNTAX, chunk_empty);
- incr_mid(this, FALSE);
+ status = send_invalid_syntax(this, msg);
}
break;
case VERIFY_ERROR:
DBG1(DBG_IKE, "message verification failed");
if (is_request)
{
- send_notify_response(this, msg,
- INVALID_SYNTAX, chunk_empty);
- incr_mid(this, FALSE);
+ status = send_invalid_syntax(this, msg);
}
break;
case FAILED:
is_request ? "request" : "response",
msg->get_message_id(msg));
- charon->bus->alert(charon->bus, ALERT_PARSE_ERROR_BODY, msg, status);
+ charon->bus->alert(charon->bus, ALERT_PARSE_ERROR_BODY, msg,
+ parse_status);
- if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED)
- { /* invalid initiation attempt, close SA */
- return DESTROY_ME;
+ switch (this->ike_sa->get_state(this->ike_sa))
+ {
+ case IKE_CREATED:
+ /* invalid initiation attempt, close SA */
+ status = DESTROY_ME;
+ break;
+ case IKE_CONNECTING:
+ case IKE_REKEYED:
+ /* don't trigger updown event in these states */
+ break;
+ default:
+ if (status == DESTROY_ME)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ }
+ break;
}
}
return status;