Change traffic selectors during Quick Mode in case of a NAT in transport mode
authorTobias Brunner <tobias@strongswan.org>
Fri, 14 Sep 2012 07:07:21 +0000 (09:07 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 14 Sep 2012 07:40:18 +0000 (09:40 +0200)
Windows 7 sends its internal address as TSi.  While we don't support the
NAT-T drafts as used by Windows XP it is interesting to note that the
client there omits the TSi payload which then would automatically get set
to the public IP address of the client.

Fixes #220.

src/libcharon/sa/ikev1/tasks/quick_mode.c

index 34cf093..916cd5b 100644 (file)
@@ -566,6 +566,15 @@ static bool get_ts(private_quick_mode_t *this, message_t *message)
                tsr = traffic_selector_create_from_subnet(hsr->clone(hsr),
                                                        hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0);
        }
+       if (!this->initiator && this->mode == MODE_TRANSPORT && this->udp &&
+          (!tsi->is_host(tsi, hsi) || !tsr->is_host(tsr, hsr)))
+       {       /* change TS in case of a NAT in transport mode */
+               DBG2(DBG_IKE, "changing received traffic selectors %R=== %R due to NAT",
+                        tsi, tsr);
+               tsi->set_address(tsi, hsi);
+               tsr->set_address(tsr, hsr);
+       }
+
        if (this->initiator)
        {
                /* check if peer selection valid */
@@ -887,6 +896,16 @@ METHOD(task_t, process_r, status_t,
                        u_int16_t group;
                        bool private;
 
+                       sa_payload = (sa_payload_t*)message->get_payload(message,
+                                                                                                       SECURITY_ASSOCIATION_V1);
+                       if (!sa_payload)
+                       {
+                               DBG1(DBG_IKE, "sa payload missing");
+                               return send_notify(this, INVALID_PAYLOAD_TYPE);
+                       }
+
+                       this->mode = sa_payload->get_encap_mode(sa_payload, &this->udp);
+
                        if (!get_ts(this, message))
                        {
                                return FAILED;
@@ -913,13 +932,6 @@ METHOD(task_t, process_r, status_t,
                                return send_notify(this, INVALID_ID_INFORMATION);
                        }
 
-                       sa_payload = (sa_payload_t*)message->get_payload(message,
-                                                                                                       SECURITY_ASSOCIATION_V1);
-                       if (!sa_payload)
-                       {
-                               DBG1(DBG_IKE, "sa payload missing");
-                               return send_notify(this, INVALID_PAYLOAD_TYPE);
-                       }
                        if (this->config->use_ipcomp(this->config))
                        {
                                if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
@@ -950,8 +962,6 @@ METHOD(task_t, process_r, status_t,
                                                                                                                   list, FALSE, private);
                        list->destroy_offset(list, offsetof(proposal_t, destroy));
 
-                       this->mode = sa_payload->get_encap_mode(sa_payload, &this->udp);
-
                        get_lifetimes(this);
                        apply_lifetimes(this, sa_payload);