message: Handle encrypted fragment payload similar to the encrypted payload
This commit is contained in:
@@ -1480,16 +1480,29 @@ static void order_payloads(private_message_t *this)
|
|||||||
*/
|
*/
|
||||||
static encrypted_payload_t* wrap_payloads(private_message_t *this)
|
static encrypted_payload_t* wrap_payloads(private_message_t *this)
|
||||||
{
|
{
|
||||||
encrypted_payload_t *encrypted;
|
encrypted_payload_t *encrypted = NULL;
|
||||||
linked_list_t *payloads;
|
linked_list_t *payloads;
|
||||||
payload_t *current;
|
payload_t *current;
|
||||||
|
|
||||||
/* copy all payloads in a temporary list */
|
/* move all payloads to a temporary list */
|
||||||
payloads = linked_list_create();
|
payloads = linked_list_create();
|
||||||
while (this->payloads->remove_first(this->payloads,
|
while (this->payloads->remove_first(this->payloads,
|
||||||
(void**)¤t) == SUCCESS)
|
(void**)¤t) == SUCCESS)
|
||||||
{
|
{
|
||||||
payloads->insert_last(payloads, current);
|
if (current->get_type(current) == PLV2_FRAGMENT)
|
||||||
|
{ /* treat encrypted fragment payload as encrypted payload */
|
||||||
|
encrypted = (encrypted_payload_t*)current;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
payloads->insert_last(payloads, current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (encrypted)
|
||||||
|
{ /* simply adopt all the unencrypted payloads */
|
||||||
|
this->payloads->destroy(this->payloads);
|
||||||
|
this->payloads = payloads;
|
||||||
|
return encrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->is_encrypted)
|
if (this->is_encrypted)
|
||||||
@@ -1688,14 +1701,17 @@ static status_t generate_message(private_message_t *this, keymat_t *keymat,
|
|||||||
payload = next;
|
payload = next;
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
next_type = PL_NONE;
|
||||||
if (this->is_encrypted)
|
if (this->is_encrypted)
|
||||||
{ /* for encrypted IKEv1 messages */
|
{ /* for encrypted IKEv1 messages */
|
||||||
next_type = (*encrypted)->payload_interface.get_next_type(
|
next_type = (*encrypted)->payload_interface.get_next_type(
|
||||||
(payload_t*)*encrypted);
|
(payload_t*)*encrypted);
|
||||||
}
|
}
|
||||||
else
|
else if (*encrypted)
|
||||||
{
|
{ /* use proper IKEv2 encrypted (fragment) payload type */
|
||||||
next_type = (*encrypted) ? PLV2_ENCRYPTED : PL_NONE;
|
next_type = (*encrypted)->payload_interface.get_type(
|
||||||
|
(payload_t*)*encrypted);
|
||||||
}
|
}
|
||||||
payload->set_next_type(payload, next_type);
|
payload->set_next_type(payload, next_type);
|
||||||
generator->generate_payload(generator, payload);
|
generator->generate_payload(generator, payload);
|
||||||
@@ -2096,9 +2112,9 @@ static status_t parse_payloads(private_message_t *this)
|
|||||||
payload_type_names, type);
|
payload_type_names, type);
|
||||||
this->payloads->insert_last(this->payloads, payload);
|
this->payloads->insert_last(this->payloads, payload);
|
||||||
|
|
||||||
/* an encrypted payload is the last one, so STOP here. decryption is
|
/* an encrypted (fragment) payload MUST be the last one, so STOP here.
|
||||||
* done later */
|
* decryption is done later */
|
||||||
if (type == PLV2_ENCRYPTED)
|
if (type == PLV2_ENCRYPTED || type == PLV2_FRAGMENT)
|
||||||
{
|
{
|
||||||
DBG2(DBG_ENC, "%N payload found, stop parsing",
|
DBG2(DBG_ENC, "%N payload found, stop parsing",
|
||||||
payload_type_names, type);
|
payload_type_names, type);
|
||||||
@@ -2194,6 +2210,41 @@ static status_t decrypt_and_extract(private_message_t *this, keymat_t *keymat,
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypt an encrypted fragment payload.
|
||||||
|
*/
|
||||||
|
static status_t decrypt_fragment(private_message_t *this, keymat_t *keymat,
|
||||||
|
encrypted_fragment_payload_t *fragment)
|
||||||
|
{
|
||||||
|
encrypted_payload_t *encrypted = (encrypted_payload_t*)fragment;
|
||||||
|
chunk_t chunk;
|
||||||
|
aead_t *aead;
|
||||||
|
size_t bs;
|
||||||
|
|
||||||
|
if (!keymat)
|
||||||
|
{
|
||||||
|
DBG1(DBG_ENC, "found encrypted fragment payload, but no keymat");
|
||||||
|
return INVALID_ARG;
|
||||||
|
}
|
||||||
|
aead = keymat->get_aead(keymat, TRUE);
|
||||||
|
if (!aead)
|
||||||
|
{
|
||||||
|
DBG1(DBG_ENC, "found encrypted fragment payload, but no transform set");
|
||||||
|
return INVALID_ARG;
|
||||||
|
}
|
||||||
|
bs = aead->get_block_size(aead);
|
||||||
|
encrypted->set_transform(encrypted, aead);
|
||||||
|
chunk = this->packet->get_data(this->packet);
|
||||||
|
if (chunk.len < encrypted->get_length(encrypted) ||
|
||||||
|
chunk.len < bs)
|
||||||
|
{
|
||||||
|
DBG1(DBG_ENC, "invalid payload length");
|
||||||
|
return VERIFY_ERROR;
|
||||||
|
}
|
||||||
|
chunk.len -= encrypted->get_length(encrypted);
|
||||||
|
return encrypted->decrypt(encrypted, chunk);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do we accept unencrypted ID/HASH payloads in Main Mode, as seen from
|
* Do we accept unencrypted ID/HASH payloads in Main Mode, as seen from
|
||||||
* some SonicWall boxes?
|
* some SonicWall boxes?
|
||||||
@@ -2222,7 +2273,7 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
|
|||||||
payload_rule_t *rule;
|
payload_rule_t *rule;
|
||||||
payload_type_t type;
|
payload_type_t type;
|
||||||
status_t status = SUCCESS;
|
status_t status = SUCCESS;
|
||||||
bool was_encrypted = FALSE;
|
char *was_encrypted = NULL;
|
||||||
|
|
||||||
enumerator = this->payloads->create_enumerator(this->payloads);
|
enumerator = this->payloads->create_enumerator(this->payloads);
|
||||||
while (enumerator->enumerate(enumerator, &payload))
|
while (enumerator->enumerate(enumerator, &payload))
|
||||||
@@ -2231,17 +2282,21 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
|
|||||||
|
|
||||||
DBG2(DBG_ENC, "process payload of type %N", payload_type_names, type);
|
DBG2(DBG_ENC, "process payload of type %N", payload_type_names, type);
|
||||||
|
|
||||||
if (type == PLV2_ENCRYPTED || type == PLV1_ENCRYPTED)
|
if (type == PLV2_ENCRYPTED || type == PLV1_ENCRYPTED ||
|
||||||
|
type == PLV2_FRAGMENT)
|
||||||
{
|
{
|
||||||
encrypted_payload_t *encryption;
|
|
||||||
|
|
||||||
if (was_encrypted)
|
if (was_encrypted)
|
||||||
{
|
{
|
||||||
DBG1(DBG_ENC, "encrypted payload can't contain other payloads "
|
DBG1(DBG_ENC, "%s can't contain other payloads of type %N",
|
||||||
"of type %N", payload_type_names, type);
|
was_encrypted, payload_type_names, type);
|
||||||
status = VERIFY_ERROR;
|
status = VERIFY_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == PLV2_ENCRYPTED || type == PLV1_ENCRYPTED)
|
||||||
|
{
|
||||||
|
encrypted_payload_t *encryption;
|
||||||
|
|
||||||
DBG2(DBG_ENC, "found an encrypted payload");
|
DBG2(DBG_ENC, "found an encrypted payload");
|
||||||
encryption = (encrypted_payload_t*)payload;
|
encryption = (encrypted_payload_t*)payload;
|
||||||
@@ -2260,7 +2315,27 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
was_encrypted = TRUE;
|
was_encrypted = "encrypted payload";
|
||||||
|
}
|
||||||
|
else if (type == PLV2_FRAGMENT)
|
||||||
|
{
|
||||||
|
encrypted_fragment_payload_t *fragment;
|
||||||
|
|
||||||
|
DBG2(DBG_ENC, "found an encrypted fragment payload");
|
||||||
|
fragment = (encrypted_fragment_payload_t*)payload;
|
||||||
|
|
||||||
|
if (enumerator->enumerate(enumerator, NULL))
|
||||||
|
{
|
||||||
|
DBG1(DBG_ENC, "encrypted fragment payload is not last payload");
|
||||||
|
status = VERIFY_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
status = decrypt_fragment(this, keymat, fragment);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
was_encrypted = "encrypted fragment payload";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload_is_known(type) && !was_encrypted &&
|
if (payload_is_known(type) && !was_encrypted &&
|
||||||
|
|||||||
Reference in New Issue
Block a user