rlm_eap: fix channel binding errors
authorSam Hartman <hartmans@debian.org>
Sat, 4 Feb 2012 01:30:33 +0000 (20:30 -0500)
committerSam Hartman <hartmans@debian.org>
Tue, 5 Mar 2013 20:04:49 +0000 (15:04 -0500)
Fix logic and other erros in initial channel binding implementation

src/modules/rlm_eap/libeap/eap_chbind.c
src/modules/rlm_eap/libeap/eap_chbind.h

index 5112528..78dcf68 100644 (file)
@@ -39,25 +39,25 @@ RCSID("$Id$")
 
 #include "eap_chbind.h"
 
-#define MAX_PACKET_LEN         1024
+#define MAX_PACKET_LEN         4096
 
 /*
  * Process any channel bindings included in the request.
  */
-CHBIND_REQ *chbind_allocate()
+CHBIND_REQ *chbind_allocate(void)
 {
   CHBIND_REQ *ret;
-  ret = malloc(sizeof CHBIND_REQUQEST);
+  ret = malloc(sizeof *ret);
   if (0 != ret)
-    memset(ret, 0, sizeof CHBIND_REQUEST);
+    memset(ret, 0, sizeof *ret);
   return ret;
 }
 
-void *chbind_free(CHBIND_REQ *chbind)
+void chbind_free(CHBIND_REQ *chbind)
 {
   /* free the chbind response, if allocated by chbind_process */
   if (chbind->chbind_resp)
-    free(chbind_resp);
+    free(chbind->chbind_resp);
 
   free(chbind);
 }
@@ -66,17 +66,15 @@ int chbind_process(REQUEST *req, CHBIND_REQ *chbind_req)
 {
   int rcode = PW_AUTHENTICATION_REJECT;
   REQUEST *fake = NULL;
-  VALUE_PAIR *user_vp = NULL;
+  VALUE_PAIR *vp = NULL;
   uint8_t *attr_data;
-  uint8_t attr_len = 0;
-  int i = 0;
+  size_t datalen = 0;
 
   /* check input parameters */
-  rad_assert((request != NULL) && 
+  rad_assert((req != NULL) && 
             (chbind_req != NULL) &&
-            (chbind_req->username != NULL) &&
-             (chbind_req->chbind_req_buf != NULL));
-  if (chbind_req->len < 4)
+            (chbind_req->chbind_req_pkt != NULL));
+  if (chbind_req->chbind_req_len < 4)
     return PW_AUTHENTICATION_REJECT;  /* Is this the right response? */
 
   /* Set-up NULL response for cases where channel bindings can't be processed */
@@ -84,7 +82,7 @@ int chbind_process(REQUEST *req, CHBIND_REQ *chbind_req)
   chbind_req->chbind_resp_len = 0;
 
   /* Set-up the fake request */
-  fake = request_alloc_fake(request);
+  fake = request_alloc_fake(req);
   rad_assert(fake->packet->vps == NULL);
   vp = pairmake("Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
   if (vp) {
@@ -92,26 +90,28 @@ int chbind_process(REQUEST *req, CHBIND_REQ *chbind_req)
   }
   
   /* Add the username to the fake request */
-  vp = paircreate(PW_USER_NAME, 0, PW_TYPE_STRING);
-  rad_assert(vp);
-  memcpy(vp->vp_octets, chbind_req->username, chbind_req->username_len);
-  vp->length = chbind_req->username_len;
+  if (chbind_req->username) {
+    vp = paircreate(PW_USER_NAME, 0, PW_TYPE_STRING);
+    rad_assert(vp);
+    memcpy(vp->vp_octets, chbind_req->username, chbind_req->username_len);
+    vp->length = chbind_req->username_len;
 
-  pairadd(&fake->packet-vps, vp);
+    pairadd(&fake->packet->vps, vp);
   fake->username = pairfind(fake->packet->vps, PW_USER_NAME, 0);
+  }
 
   /* Copy the request state into the fake request */
-  vp = paircopy(req->state);
+  /*xxx vp = paircopy(req->state);
   if (vp)
-    pairadd(&fake->packet->vps, vp);
+  pairadd(&fake->packet->vps, vp);*/
 
   /* Add the channel binding attributes to the fake packet */
-  if (0 != (datalen = chbind_get_data((chbind_packet_t *)chbind_req, chbind_req_len, 
+  if (0 != (datalen = chbind_get_data((CHBIND_PACKET_T *)chbind_req->chbind_req_pkt, chbind_req->chbind_req_len, 
                                      CHBIND_NSID_RADIUS, &attr_data))) {
-    if (0 < radattr2vp(NULL, NULL, NULL, attr_data, datalen, &vp)) {
+    if (rad_attr2vp(NULL, NULL, NULL, attr_data, datalen, &vp) <= 0) {
       /* If radaddr2vp fails, return NULL string for channel binding response */
-      request_free(fake);
-      return PW_AUTHENTICATION_OK;
+      request_free(&fake);
+      return PW_AUTHENTICATION_ACK;
     }
     if (vp)
       pairadd(&fake->packet->vps, vp);
@@ -122,9 +122,9 @@ int chbind_process(REQUEST *req, CHBIND_REQ *chbind_req)
   fake->server = pairmake("Virtual-Server", "chbind", T_OP_EQ);
 
   /* Call rad_authenticate */
-  rad_authenticate(fake);
+  rcode = rad_authenticate(fake);
 
-  switch(fake->reply->code) {
+  switch(rcode) {
     /* If rad_authenticate succeeded, build a reply */
   case RLM_MODULE_OK:
   case RLM_MODULE_HANDLED:
@@ -140,7 +140,7 @@ int chbind_process(REQUEST *req, CHBIND_REQ *chbind_req)
     break;
   }
 
-  request_free(fake);
+  request_free(&fake);
 
   return rcode;
 }
@@ -150,7 +150,7 @@ int chbind_process(REQUEST *req, CHBIND_REQ *chbind_req)
  * See http://tools.ietf.org/html/draft-ietf-emu-chbind-13#section-5.3.2:
  */ 
 
-size_t chbind_get_data(chbind_packet_t *chbind_packet,
+size_t chbind_get_data(CHBIND_PACKET_T *chbind_packet,
                           size_t chbind_packet_len,
                           int desired_nsid,
                           uint8_t **radbuf_data)
@@ -181,33 +181,35 @@ size_t chbind_get_data(chbind_packet_t *chbind_packet,
   return 0;
 }
 
-uint8_t *chbind_build_response(REQUEST *req, int *resp_len)
+uint8_t *chbind_build_response(REQUEST *req, size_t *resp_len)
 {
   uint8_t *resp, *rp = NULL;
   uint16_t rlen, len = 0;
+  VALUE_PAIR *vp = NULL;
 
   *resp_len = 0;
   resp = malloc(MAX_PACKET_LEN + 4);
   rad_assert(resp);
 
   /* Set-up the chbind header fields (except length, computed later) */
-  vp = pairfind(fake->config_items, PW_CHBIND_RESPONSE_CODE, 0);
-  resp[0] = vp->vp_integer;
+  vp = pairfind(req->config_items, PW_CHBIND_RESPONSE_CODE, 0);
+  if (vp)
+    resp[0] = vp->vp_integer;
+  else resp[0] = 3; /*failure*/
+  
 
   resp[3] = CHBIND_NSID_RADIUS;
 
   /* Encode the chbind attributes into the response */
-  for (vp = fake->reply->vps, rlen = 4; 
+  for (vp = req->reply->vps, rlen = 4; 
        (vp != NULL) && (rlen < MAX_PACKET_LEN + 4); 
        rlen += len) {
-    len = rad_vp2attr(NULL, NULL, NULL, *vp, resp[rlen], (MAX_PACKET_LEN + 4) - rlen);
+    len = rad_vp2attr(NULL, NULL, NULL, vp, resp[rlen], (MAX_PACKET_LEN + 4) - rlen);
   }
 
   /* Write the length field into the header */
   resp[1] = (uint8_t)(rlen >> 8);
   resp[2] = (uint8_t)(rlen & 0x00FF);
-    size_t len = (chbind_packet->data[pos] << 8) + 
-      chbind_packet->data[pos + 1];
   
   /* Output the length of the entire response (attrs + header) */
   *resp_len = rlen + 4;
index 29ee069..0043337 100644 (file)
@@ -50,20 +50,20 @@ RCSIDH(eap_chbind_h, "$Id$")
 #include "eap.h"
 
 /* Structure to hold channel bindings req/resp information */
-typdef struct CHBIND_REQ {
+typedef struct CHBIND_REQ {
   uint8_t       *username;             /* the username */
   size_t        username_len;           /* length of the username */
-  uint8_t      *chbind_req;            /* channel binding request buffer */
+  uint8_t      *chbind_req_pkt;            /* channel binding request buffer */
   size_t       chbind_req_len;         /* length of the request buffer */
   uint8_t       *chbind_resp;           /* channel binding response buffer */
   size_t        chbind_resp_len;        /* length of the response buffer */
-};
+} CHBIND_REQ;
 
 /* Structure to represent eap channel binding packet format */
 typedef struct chbind_packet_t {
   uint8_t code;
   uint8_t data[1];
-} eap_chbind_packet_t;
+} CHBIND_PACKET_T;
 
 /* Protocol constants */
 #define CHBIND_NSID_RADIUS             1
@@ -73,9 +73,10 @@ typedef struct chbind_packet_t {
 #define CHBIND_CODE_FAILURE             3
 
 /* Channel binding function prototypes */
-CHBIND_REQ *chbind_allocate();
-void *chbind_free(CHBIND_REQ *chbind);
+CHBIND_REQ *chbind_allocate(void);
+void chbind_free(CHBIND_REQ *chbind);
 int chbind_process(REQUEST *req, CHBIND_REQ *chbind_req);
-size_t chbind_get_data(chbind_packet_t *chbind_packet, size_t chbind_packet_len, int desired_nsid, uint8_t **radbuf_data);
-uint8_t *chbind_build_response(REQUEST *req, int *resp_len);
+size_t chbind_get_data(CHBIND_PACKET_T *chbind_packet, size_t chbind_packet_len, int desired_nsid, uint8_t **radbuf_data);
+uint8_t *chbind_build_response(REQUEST *req, size_t *resp_len);
 
+#endif /*_EAP_CHBIND_H*/