libipsec: check for a policy with the reqid of the SA on decapsulation
To prevent a client from sending a packet with a source address of a different client, we require a policy bound via reqid to the decapsulating SA.
This commit is contained in:
@@ -230,7 +230,8 @@ METHOD(ipsec_policy_mgr_t, flush_policies, status_t,
|
|||||||
}
|
}
|
||||||
|
|
||||||
METHOD(ipsec_policy_mgr_t, find_by_packet, ipsec_policy_t*,
|
METHOD(ipsec_policy_mgr_t, find_by_packet, ipsec_policy_t*,
|
||||||
private_ipsec_policy_mgr_t *this, ip_packet_t *packet, bool inbound)
|
private_ipsec_policy_mgr_t *this, ip_packet_t *packet, bool inbound,
|
||||||
|
u_int32_t reqid)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
ipsec_policy_entry_t *current;
|
ipsec_policy_entry_t *current;
|
||||||
@@ -245,8 +246,11 @@ METHOD(ipsec_policy_mgr_t, find_by_packet, ipsec_policy_t*,
|
|||||||
if ((inbound == (policy->get_direction(policy) == POLICY_IN)) &&
|
if ((inbound == (policy->get_direction(policy) == POLICY_IN)) &&
|
||||||
policy->match_packet(policy, packet))
|
policy->match_packet(policy, packet))
|
||||||
{
|
{
|
||||||
found = policy->get_ref(policy);
|
if (reqid == 0 || reqid == policy->get_reqid(policy))
|
||||||
break;
|
{
|
||||||
|
found = policy->get_ref(policy);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|||||||
@@ -97,10 +97,12 @@ struct ipsec_policy_mgr_t {
|
|||||||
*
|
*
|
||||||
* @param packet IP packet to match
|
* @param packet IP packet to match
|
||||||
* @param inbound TRUE for an inbound packet
|
* @param inbound TRUE for an inbound packet
|
||||||
|
* @param reqid require a policy with a specific reqid, 0 for any
|
||||||
* @return reference to the policy, or NULL if none found
|
* @return reference to the policy, or NULL if none found
|
||||||
*/
|
*/
|
||||||
ipsec_policy_t *(*find_by_packet)(ipsec_policy_mgr_t *this,
|
ipsec_policy_t *(*find_by_packet)(ipsec_policy_mgr_t *this,
|
||||||
ip_packet_t *packet, bool inbound);
|
ip_packet_t *packet, bool inbound,
|
||||||
|
u_int32_t reqid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy an ipsec_policy_mgr_t
|
* Destroy an ipsec_policy_mgr_t
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ static job_requeue_t process_inbound(private_ipsec_processor_t *this)
|
|||||||
esp_packet_t *packet;
|
esp_packet_t *packet;
|
||||||
ipsec_sa_t *sa;
|
ipsec_sa_t *sa;
|
||||||
u_int8_t next_header;
|
u_int8_t next_header;
|
||||||
u_int32_t spi;
|
u_int32_t spi, reqid;
|
||||||
|
|
||||||
packet = (esp_packet_t*)this->inbound_queue->dequeue(this->inbound_queue);
|
packet = (esp_packet_t*)this->inbound_queue->dequeue(this->inbound_queue);
|
||||||
|
|
||||||
@@ -126,6 +126,7 @@ static job_requeue_t process_inbound(private_ipsec_processor_t *this)
|
|||||||
packet->destroy(packet);
|
packet->destroy(packet);
|
||||||
return JOB_REQUEUE_DIRECT;
|
return JOB_REQUEUE_DIRECT;
|
||||||
}
|
}
|
||||||
|
reqid = sa->get_reqid(sa);
|
||||||
ipsec->sas->checkin(ipsec->sas, sa);
|
ipsec->sas->checkin(ipsec->sas, sa);
|
||||||
|
|
||||||
next_header = packet->get_next_header(packet);
|
next_header = packet->get_next_header(packet);
|
||||||
@@ -139,7 +140,7 @@ static job_requeue_t process_inbound(private_ipsec_processor_t *this)
|
|||||||
|
|
||||||
ip_packet = packet->get_payload(packet);
|
ip_packet = packet->get_payload(packet);
|
||||||
policy = ipsec->policies->find_by_packet(ipsec->policies,
|
policy = ipsec->policies->find_by_packet(ipsec->policies,
|
||||||
ip_packet, TRUE);
|
ip_packet, TRUE, reqid);
|
||||||
if (policy)
|
if (policy)
|
||||||
{ /* TODO-IPSEC: update policy/sa stats? */
|
{ /* TODO-IPSEC: update policy/sa stats? */
|
||||||
deliver_inbound(this, packet);
|
deliver_inbound(this, packet);
|
||||||
@@ -193,7 +194,7 @@ static job_requeue_t process_outbound(private_ipsec_processor_t *this)
|
|||||||
|
|
||||||
packet = (ip_packet_t*)this->outbound_queue->dequeue(this->outbound_queue);
|
packet = (ip_packet_t*)this->outbound_queue->dequeue(this->outbound_queue);
|
||||||
|
|
||||||
policy = ipsec->policies->find_by_packet(ipsec->policies, packet, FALSE);
|
policy = ipsec->policies->find_by_packet(ipsec->policies, packet, FALSE, 0);
|
||||||
if (!policy)
|
if (!policy)
|
||||||
{
|
{
|
||||||
DBG2(DBG_ESP, "no matching outbound IPsec policy for %H == %H",
|
DBG2(DBG_ESP, "no matching outbound IPsec policy for %H == %H",
|
||||||
|
|||||||
Reference in New Issue
Block a user