Eap channel binding support code
authorKevin <kevin@debian.suchdamage.org>
Fri, 3 Feb 2012 13:15:10 +0000 (08:15 -0500)
committerSam Hartman <hartmans@debian.org>
Tue, 5 Mar 2013 20:04:49 +0000 (15:04 -0500)
src/include/radius.h
src/modules/rlm_eap/libeap/eap_types.h
src/modules/rlm_eap/libeap/eapcommon.c
src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c

index 3ab0f56..f8350cb 100644 (file)
@@ -331,6 +331,7 @@ typedef enum {
 #define VENDORPEC_MICROSOFT            311
 #define VENDORPEC_FREERADIUS           11344
 #define VENDORPEC_WIMAX                        24757
+#define VENDORPEC_UKERNA               25622
 
 /*
  * Vendor specific attributes
@@ -374,3 +375,9 @@ typedef enum {
 #define PW_VQP_MAC                     0x2c06
 #define PW_VQP_UNKNOWN                 0x2c07
 #define PW_VQP_COOKIE                  0x2c08
+
+/*
+ * JANET's code for transporting eap channel binding data over ttls
+ */
+
+#define PW_UKERNA_CHBIND               134
index c4b24c8..836d23a 100644 (file)
@@ -111,6 +111,14 @@ typedef struct eap_packet_t {
        uint8_t         data[1];
 } eap_packet_t;
 
+/*
+ * Structure to represent eap channel binding packet format *on wire*
+ */
+typedef struct eap_chbind_packet_t {
+       uint8_t         code;
+       uint8_t         data[1];
+} eap_chbind_packet_t;
+
 
 /*
  * interfaces in eapcommon.c
@@ -121,5 +129,7 @@ extern int eap_wireformat(EAP_PACKET *reply);
 extern int eap_basic_compose(RADIUS_PACKET *packet, EAP_PACKET *reply);
 extern VALUE_PAIR *eap_packet2vp(const eap_packet_t *reply);
 extern eap_packet_t *eap_vp2packet(VALUE_PAIR *vps);
+extern VALUE_PAIR *eap_chbind_packet2vp(const eap_chbind_packet_t *packet, size_t len);
+extern size_t eap_chbind_vp2packet(VALUE_PAIR *vps, eap_chbind_packet_t **packet);
 
 #endif /* _EAP_TYPES_H */
index 67f751f..0ad65cc 100644 (file)
@@ -432,3 +432,102 @@ eap_packet_t *eap_vp2packet(VALUE_PAIR *vps)
 
        return eap_packet;
 }
+
+VALUE_PAIR *eap_chbind_packet2vp(const eap_chbind_packet_t *packet, size_t len)
+{
+       size_t          size;
+       const uint8_t   *ptr;
+       VALUE_PAIR      *head = NULL;
+       VALUE_PAIR      **tail = &head;
+       VALUE_PAIR      *vp;
+
+       ptr = (const uint8_t *) packet;
+
+       do {
+               size = len;
+               if (size > 247) size = 247;
+
+               vp = paircreate(PW_VENDOR_SPECIFIC, VENDORPEC_UKERNA,
+                               PW_TYPE_OCTETS);
+               if (!vp) {
+                       pairfree(&head);
+                       return NULL;
+               }
+               vp->vp_octets[0] = PW_UKERNA_CHBIND;
+               vp->vp_octets[1] = size;
+               memcpy(&vp->vp_octets[2], ptr, size);
+               vp->length = size + 2;
+
+               *tail = vp;
+               tail = &(vp->next);
+
+               ptr += size;
+               len -= size;
+       } while (len > 0);
+
+       return head;
+}
+
+
+/*
+ * Find the next EAP-CHANNEL-BINDING message in the 
+ * pair list
+ */
+static VALUE_PAIR *eap_chbind_find_pair(VALUE_PAIR *vps)
+{
+       VALUE_PAIR *result = pairfind(vps, PW_VENDOR_SPECIFIC, 
+                                     VENDORPEC_UKERNA);
+        while (result && (result->vp_octets[0] != PW_UKERNA_CHBIND))
+               result = result->next;
+       return result;
+}
+
+/*
+ * Handles multiple EAP-channel-binding Message attrs
+ * ie concatenates all to get the complete EAP-channel-binding packet.
+ */
+size_t eap_chbind_vp2packet(VALUE_PAIR *vps, eap_chbind_packet_t **result)
+{
+       VALUE_PAIR *first, *vp;
+       eap_chbind_packet_t *eap_chbind_packet;
+       unsigned char *ptr;
+       size_t len;
+
+       first = eap_chbind_find_pair(vps);
+
+       /*
+        *      Sanity check the length, BEFORE malloc'ing memory.
+        */
+       len = 0;
+       for (vp = first; vp; vp = eap_chbind_find_pair(vp)) {
+               if ((vp->length < 2) ||
+                   (vp->length != vp->vp_octets[1]+2)) {
+                       DEBUG("rlm_eap: Malformed EAP channel binding value pair.  Length in pair header does not match actual length");
+                       return 0;
+               }
+               len += vp->vp_octets[1];
+       }
+
+       /*
+        *      Now that we know the lengths are OK, allocate memory.
+        */
+       eap_chbind_packet = (eap_chbind_packet_t *) malloc(len);
+       if (eap_chbind_packet == NULL) {
+               radlog(L_ERR, "rlm_eap: out of memory");
+               return 0;
+       }
+
+       /*
+        *      Copy the data from EAP-Message's over to our EAP packet.
+        */
+       ptr = (unsigned char *)eap_chbind_packet;
+
+       /* RADIUS ensures order of attrs, so just concatenate all */
+       for (vp = first; vp; vp = eap_chbind_find_pair(vp->next)) {
+               memcpy(ptr, vp->vp_octets+2, vp->length-2);
+               ptr += vp->length-2;
+       }
+
+       *result = eap_chbind_packet;
+       return len;
+}
index 3ee5d01..12a6028 100644 (file)
@@ -973,6 +973,8 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
        const uint8_t *data;
        size_t data_len;
        REQUEST *request = handler->request;
+       eap_chbind_packet_t *chbind_packet;
+       size_t chbind_len;
 
        rad_assert(request != NULL);
 
@@ -1213,6 +1215,36 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
        }
 
        /*
+        *      Process channel binding here.
+        */
+       chbind_len = eap_chbind_vp2packet(fake->packet->vps, &chbind_packet);
+       if (chbind_len > 0) {
+               /*CHBIND_REQ *req = chbind_allocate();
+               req->chbind_req = chbind_packet;
+               req->chbind_req_len = chbind_len;
+               if (fake->username) {
+                       req->username = fake->username->vp_octets;
+                       req->username_len = fake->username->length;
+               } else {
+                       req->username = NULL;
+                       req->username_len = 0;
+               }
+               chbind_process(request, req);
+               */
+
+               /* free the chbind packet; we're done with it */
+               free(chbind_packet);
+
+               /* encapsulate response here */
+               /*pairadd(replyvps, eap_chbind_packet2vp(req->chbind_resp,
+                                                      req->chbind_resp_len));
+               */
+
+               /* clean up chbind req */
+               /*chbind_free(req);*/
+       }
+
+       /*
         *      Call authentication recursively, which will
         *      do PAP, CHAP, MS-CHAP, etc.
         */