From: Sam Hartman Date: Sat, 4 Feb 2012 01:30:33 +0000 (-0500) Subject: rlm_eap: fix channel binding errors X-Git-Tag: trustrouter-1.0~1^2~12 X-Git-Url: http://www.project-moonshot.org/gitweb/?a=commitdiff_plain;h=8b1d5821d8b5b02549c5beeca6a3efa0a44bc7c8;hp=d897b4a22f6ddd52f55795ed2dade8b885a108c3;p=freeradius.git rlm_eap: fix channel binding errors Fix logic and other erros in initial channel binding implementation --- diff --git a/src/modules/rlm_eap/libeap/eap_chbind.c b/src/modules/rlm_eap/libeap/eap_chbind.c index 5112528..78dcf68 100644 --- a/src/modules/rlm_eap/libeap/eap_chbind.c +++ b/src/modules/rlm_eap/libeap/eap_chbind.c @@ -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; diff --git a/src/modules/rlm_eap/libeap/eap_chbind.h b/src/modules/rlm_eap/libeap/eap_chbind.h index 29ee069..0043337 100644 --- a/src/modules/rlm_eap/libeap/eap_chbind.h +++ b/src/modules/rlm_eap/libeap/eap_chbind.h @@ -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*/