libeap: ttls: encapsulate using RADIUS VSA
authorSam Hartman <hartmans@debian.org>
Fri, 22 Mar 2013 18:01:23 +0000 (14:01 -0400)
committerSam Hartman <hartmans@debian.org>
Tue, 26 Mar 2013 02:12:36 +0000 (22:12 -0400)
It turns out that older version of FreeRADIUS will fail if they
receive a diameter VSA not in their dictionary.  A RADIUS VSA is fine
though.  This does not comply with the TTLS spec, but is the best we
can do in terms of interoperability, so do that.

libeap/src/eap_common/eap_ttls.h
libeap/src/eap_peer/eap_ttls.c

index 401b163..08f371c 100644 (file)
@@ -35,6 +35,7 @@ struct ttls_avp_vendor {
        /* Data */
 };
 
+
 #define AVP_FLAGS_VENDOR 0x80
 #define AVP_FLAGS_MANDATORY 0x40
 
index ef966cb..40d160d 100644 (file)
@@ -15,6 +15,7 @@
 #include "includes.h"
 
 #include "common.h"
+#include "radius/radius.h"
 #include "crypto/ms_funcs.h"
 #include "crypto/sha1.h"
 #include "crypto/tls.h"
@@ -263,14 +264,14 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
 }
 
 /* chop up resp into multiple vsa's as necessary*/
-static int eap_ttls_avp_vsa_encapsulate(struct wpabuf **resp, u32 vendor,
+static int eap_ttls_avp_radius_vsa_encapsulate(struct wpabuf **resp, u32 vendor,
                                        u8 attr, int mandatory)
 {
        struct wpabuf *msg;
-       u8 *avp, *pos, *src;
+       u8 *avp, *pos, *src, *final;
        size_t size = wpabuf_len(*resp);
        size_t num_msgs = 1 + (size / 248);
-       size_t msg_wrapper_size = sizeof(struct ttls_avp_vendor) + 4;
+       size_t msg_wrapper_size = sizeof(struct ttls_avp_vendor) + 6;
        size_t allocated_total = num_msgs * (4 + msg_wrapper_size) + size;
 
        msg = wpabuf_alloc(allocated_total);
@@ -284,14 +285,20 @@ static int eap_ttls_avp_vsa_encapsulate(struct wpabuf **resp, u32 vendor,
        while (size > 0) {
                int avp_size = size > 248 ? 248 : size;
                size -= avp_size;
-               pos = eap_ttls_avp_hdr(avp, attr, vendor, mandatory,
-                                      avp_size);
-               os_memcpy(pos, src, avp_size);
-               pos += avp_size;
+               pos = eap_ttls_avp_hdr(avp, RADIUS_ATTR_VENDOR_SPECIFIC, 0, mandatory,
+                                      avp_size+6);
+               wpabuf_put(msg, pos-avp);
+               wpabuf_put_be32(msg, vendor);
+               wpabuf_put_u8(msg, (u8) attr);
+               wpabuf_put_u8(msg, (u8) avp_size+2);
+               wpabuf_put_data(msg, src, avp_size);
                src += avp_size;
-               AVP_PAD(avp, pos);
-               wpabuf_put(msg, pos - avp);
-               avp = pos;
+               pos = wpabuf_mhead_u8(msg) + wpabuf_len(msg);
+               final = pos; /*keep pos so we know how much padding is added*/
+               AVP_PAD(avp, final); /*final modified*/
+               if (final > pos)
+                       wpabuf_put(msg, final-pos);
+               avp = final;
        }
        /* check avp-wpabuf_mhead(msg) < allocated_total */
        wpabuf_free(*resp);
@@ -1385,7 +1392,7 @@ static int eap_ttls_add_chbind_request(struct eap_sm *sm,
                wpabuf_put_data(chbind_req, chbind_config->req_data,
                                chbind_config->req_data_len);
        }
-       if (eap_ttls_avp_vsa_encapsulate(&chbind_req,
+       if (eap_ttls_avp_radius_vsa_encapsulate(&chbind_req,
                                         RADIUS_VENDOR_ID_UKERNA,
                                         RADIUS_ATTR_UKERNA_CHBIND, 0) < 0)
                return -1;