ikev1: Send and verify IPv6 addresses correctly
authorTobias Brunner <tobias@strongswan.org>
Wed, 10 Feb 2016 09:11:31 +0000 (10:11 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 3 Mar 2016 16:32:03 +0000 (17:32 +0100)
According to the mode-config draft there is no prefix sent for
IPv6 addresses in IKEv1.  We still accept 17 bytes long addresses for
backwards compatibility with older strongSwan releases.

Fixes #1304.

src/libcharon/encoding/payloads/configuration_attribute.c
src/libcharon/sa/ikev1/tasks/mode_config.c

index 481bb7b..0bc9470 100644 (file)
@@ -144,6 +144,13 @@ METHOD(payload_t, verify, status_t,
                        }
                        break;
                case INTERNAL_IP6_ADDRESS:
+                       if (this->type == PLV1_CONFIGURATION_ATTRIBUTE &&
+                               this->length_or_value == 16)
+                       {       /* 16 bytes are correct for IKEv1, but older releases sent a
+                                * prefix byte so we still accept 0 or 17 as in IKEv2 */
+                               break;
+                       }
+                       /* fall-through */
                case INTERNAL_IP6_SUBNET:
                        if (this->length_or_value != 0 && this->length_or_value != 17)
                        {
index a03477e..b9f9240 100644 (file)
@@ -76,35 +76,20 @@ typedef struct {
  */
 static configuration_attribute_t *build_vip(host_t *vip)
 {
-       configuration_attribute_type_t type;
-       chunk_t chunk, prefix;
+       configuration_attribute_type_t type = INTERNAL_IP4_ADDRESS;
+       chunk_t chunk;
 
-       if (vip->get_family(vip) == AF_INET)
+       if (vip->get_family(vip) == AF_INET6)
        {
-               type = INTERNAL_IP4_ADDRESS;
-               if (vip->is_anyaddr(vip))
-               {
-                       chunk = chunk_empty;
-               }
-               else
-               {
-                       chunk = vip->get_address(vip);
-               }
+               type = INTERNAL_IP6_ADDRESS;
+       }
+       if (vip->is_anyaddr(vip))
+       {
+               chunk = chunk_empty;
        }
        else
        {
-               type = INTERNAL_IP6_ADDRESS;
-               if (vip->is_anyaddr(vip))
-               {
-                       chunk = chunk_empty;
-               }
-               else
-               {
-                       prefix = chunk_alloca(1);
-                       *prefix.ptr = 64;
-                       chunk = vip->get_address(vip);
-                       chunk = chunk_cata("cc", chunk, prefix);
-               }
+               chunk = vip->get_address(vip);
        }
        return configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE,
                                                                                                type, chunk);
@@ -165,8 +150,8 @@ static void process_attribute(private_mode_config_t *this,
                        }
                        else
                        {
-                               /* skip prefix byte in IPv6 payload*/
-                               if (family == AF_INET6)
+                               /* skip prefix byte in IPv6 payload sent by older releases */
+                               if (family == AF_INET6 && addr.len == 17)
                                {
                                        addr.len--;
                                }