ike-natd: Create fake NAT-D payloads in a more static way
authorTobias Brunner <tobias@strongswan.org>
Fri, 25 Sep 2015 17:24:44 +0000 (19:24 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 9 Nov 2015 15:25:59 +0000 (16:25 +0100)
In some scenarios an IKE_SA might get restarted multiple times (e.g.
due to retransmits and delayed INVALID_KE_PAYLOAD notifies) so that
two IKE_SA_INIT messages might be sent that only differ in the
previously randomly generated NAT_DETECTION_SOURCE_IP payload.
This could cause an authentication failure on the responder if the two
peers don't use the same IKE_SA_INIT message in their InitiatorSignedOctets.

While the payload is generated in a reproducible way it will still change
when the daemon is restarted, which should make detecting the payloads
as fake a bit harder (compared to e.g. just using 0.0.0.0:0 as address).

Fixes #1131.

src/libcharon/sa/ikev2/tasks/ike_natd.c

index 9e0eb68..dd34c12 100644 (file)
@@ -129,25 +129,6 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this,
 }
 
 /**
- * build a faked NATD payload to enforce UDP encap
- */
-static chunk_t generate_natd_hash_faked(private_ike_natd_t *this)
-{
-       rng_t *rng;
-       chunk_t chunk;
-
-       rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
-       if (!rng || !rng->allocate_bytes(rng, HASH_SIZE_SHA1, &chunk))
-       {
-               DBG1(DBG_IKE, "unable to get random bytes for NATD fake");
-               DESTROY_IF(rng);
-               return chunk_empty;
-       }
-       rng->destroy(rng);
-       return chunk;
-}
-
-/**
  * Build a NAT detection notify payload.
  */
 static notify_payload_t *build_natd_payload(private_ike_natd_t *this,
@@ -162,7 +143,14 @@ static notify_payload_t *build_natd_payload(private_ike_natd_t *this,
        config = this->ike_sa->get_ike_cfg(this->ike_sa);
        if (force_encap(config) && type == NAT_DETECTION_SOURCE_IP)
        {
-               hash = generate_natd_hash_faked(this);
+               u_int32_t addr;
+
+               /* chunk_hash() is randomly keyed so this produces a random IPv4 address
+                * that changes with every restart but otherwise stays the same */
+               addr = chunk_hash(chunk_from_chars(0x00, 0x00, 0x00, 0x00));
+               host = host_create_from_chunk(AF_INET, chunk_from_thing(addr), 0);
+               hash = generate_natd_hash(this, ike_sa_id, host);
+               host->destroy(host);
        }
        else
        {