/*
* Extract the data from the LEAP packet.
*/
-leap_packet_t *eapleap_extract(EAP_DS *eap_ds)
+leap_packet_t *eapleap_extract(REQUEST *request, EAP_DS *eap_ds)
{
leap_packet_raw_t *data;
- leap_packet_t *packet;
- int name_len;
+ leap_packet_t *packet;
+ int name_len;
/*
* LEAP can have EAP-Response or EAP-Request (step 5)
* messages sent to it.
*/
- if (!eap_ds ||
- !eap_ds->response ||
- ((eap_ds->response->code != PW_EAP_RESPONSE) &&
- (eap_ds->response->code != PW_EAP_REQUEST)) ||
- eap_ds->response->type.num != PW_EAP_LEAP ||
- !eap_ds->response->type.data ||
- (eap_ds->response->length < LEAP_HEADER_LEN) ||
- (eap_ds->response->type.data[0] != 0x01)) { /* version 1 */
- ERROR("rlm_eap_leap: corrupted data");
+ if (!eap_ds || !eap_ds->response ||
+ ((eap_ds->response->code != PW_EAP_RESPONSE) && (eap_ds->response->code != PW_EAP_REQUEST)) ||
+ (eap_ds->response->type.num != PW_EAP_LEAP) || !eap_ds->response->type.data ||
+ (eap_ds->response->length < LEAP_HEADER_LEN) ||
+ (eap_ds->response->type.data[0] != 0x01)) { /* version 1 */
+ REDEBUG("Corrupted data");
return NULL;
}
switch (eap_ds->response->code) {
case PW_EAP_RESPONSE:
if (data->count != 24) {
- ERROR("rlm_eap_leap: Bad NTChallengeResponse in LEAP stage 3");
+ REDEBUG("Bad NTChallengeResponse in LEAP stage 3");
return NULL;
}
break;
case PW_EAP_REQUEST:
if (data->count != 8) {
- ERROR("rlm_eap_leap: Bad AP Challenge in LEAP stage 5");
+ REDEBUG("Bad AP Challenge in LEAP stage 5");
return NULL;
}
break;
default:
- ERROR("rlm_eap_leap: Invalid EAP code %d",
- eap_ds->response->code);
+ REDEBUG("Invalid EAP code %d", eap_ds->response->code);
return NULL;
break;
}
talloc_free(packet);
return NULL;
}
- memcpy(packet->name, &data->challenge[packet->count],
- name_len);
+ memcpy(packet->name, &data->challenge[packet->count], name_len);
packet->name[name_len] = '\0';
packet->name_len = name_len;
}
/*
* Get the NT-Password hash.
*/
-static int eapleap_ntpwdhash(uint8_t *out, VALUE_PAIR *password)
+static int eapleap_ntpwdhash(uint8_t *out, REQUEST *request, VALUE_PAIR *password)
{
if ((password->da->attr == PW_USER_PASSWORD) ||
(password->da->attr == PW_CLEARTEXT_PASSWORD)) {
*/
len = fr_utf8_to_ucs2(ucs2_password, sizeof(ucs2_password), password->vp_strvalue, password->length);
if (len < 0) {
- ERROR("rlm_eap_leap: Error converting password to UCS2");
+ REDEBUG("Error converting password to UCS2");
return 0;
}
password->length = fr_hex2bin(p, password->vp_strvalue, 16);
}
if (password->length != 16) {
- ERROR("rlm_eap_leap: Bad NT-Password");
+ REDEBUG("Bad NT-Password");
return 0;
}
/*
* Verify the MS-CHAP response from the user.
*/
-int eapleap_stage4(leap_packet_t *packet, VALUE_PAIR* password,
- leap_session_t *session)
+int eapleap_stage4(REQUEST *request, leap_packet_t *packet, VALUE_PAIR *password, leap_session_t *session)
{
- unsigned char out[16];
- unsigned char response[24];
-
+ uint8_t hash[16];
+ uint8_t response[24];
/*
* No password or previous packet. Die.
return 0;
}
- if (!eapleap_ntpwdhash(out, password)) {
+ if (!eapleap_ntpwdhash(hash, request, password)) {
return 0;
}
/*
* Calculate and verify the CHAP challenge.
*/
- eapleap_mschap(out, session->peer_challenge, response);
+ eapleap_mschap(hash, session->peer_challenge, response);
if (memcmp(response, packet->challenge, 24) == 0) {
- DEBUG2(" rlm_eap_leap: NtChallengeResponse from AP is valid");
+ RDEBUG2("NTChallengeResponse from AP is valid");
memcpy(session->peer_response, response, sizeof(response));
return 1;
}
+ REDEBUG("FAILED incorrect NtChallengeResponse from AP");
- DEBUG2(" rlm_eap_leap: FAILED incorrect NtChallengeResponse from AP");
return 0;
}
/*
* Verify ourselves to the AP
*/
-leap_packet_t *eapleap_stage6(leap_packet_t *packet, REQUEST *request, VALUE_PAIR *user_name, VALUE_PAIR *password,
+leap_packet_t *eapleap_stage6(REQUEST *request, leap_packet_t *packet, VALUE_PAIR *user_name, VALUE_PAIR *password,
leap_session_t *session)
{
- size_t i;
- uint8_t out[16], outhash[16];
- uint8_t *p, buffer[256];
- leap_packet_t *reply;
- char *q;
- VALUE_PAIR *vp;
+ size_t i;
+ uint8_t hash[16], mppe[16];
+ uint8_t *p, buffer[256];
+ leap_packet_t *reply;
+ char *q;
+ VALUE_PAIR *vp;
/*
* No password or previous packet. Die.
/*
* MPPE hash = ntpwdhash(ntpwdhash(unicode(pw)))
*/
- if (!eapleap_ntpwdhash(out, password)) {
+ if (!eapleap_ntpwdhash(hash, request, password)) {
talloc_free(reply);
return NULL;
}
- fr_md4_calc(outhash, out, 16);
+ fr_md4_calc(mppe, hash, 16);
/*
* Calculate our response, to authenticate ourselves to the AP.
*/
- eapleap_mschap(outhash, packet->challenge, reply->challenge);
+ eapleap_mschap(mppe, packet->challenge, reply->challenge);
/*
* Calculate the leap:session-key attribute
*/
vp = pairmake_reply("Cisco-AVPair", NULL, T_OP_ADD);
if (!vp) {
- ERROR("rlm_eap_leap: Failed to create Cisco-AVPair attribute. LEAP cancelled.");
+ REDEBUG("Failed to create Cisco-AVPair attribute. LEAP cancelled");
talloc_free(reply);
return NULL;
}
* And calculate the MPPE session key.
*/
p = buffer;
- memcpy(p, outhash, 16); /* MPPEHASH */
+ memcpy(p, mppe, 16); /* MPPEHASH */
p += 16;
memcpy(p, packet->challenge, 8); /* APC */
p += 8;
/*
* These 16 bytes are the session key to use.
*/
- fr_md5_calc(out, buffer, 16 + 8 + 24 + 8 + 24);
+ fr_md5_calc(hash, buffer, 16 + 8 + 24 + 8 + 24);
q = talloc_array(vp, char, 16 + sizeof("leap:session-key="));
strcpy(q, "leap:session-key=");
- memcpy(q + 17, out, 16);
+ memcpy(q + 17, hash, 16);
i = 16;
- rad_tunnel_pwencode(q + 17, &i,
- request->client->secret, request->packet->vector);
+ rad_tunnel_pwencode(q + 17, &i, request->client->secret, request->packet->vector);
vp->length = 17 + i;
// talloc_free(vp->vp_strvalue);
vp->vp_strvalue = q;
* If an EAP LEAP request needs to be initiated then
* create such a packet.
*/
-leap_packet_t *eapleap_initiate(EAP_DS *eap_ds, VALUE_PAIR *user_name)
+leap_packet_t *eapleap_initiate(REQUEST *request, EAP_DS *eap_ds, VALUE_PAIR *user_name)
{
int i;
leap_packet_t *reply;
for (i = 0; i < reply->count; i++) {
reply->challenge[i] = fr_rand();
}
-
- DEBUG2(" rlm_eap_leap: Issuing AP Challenge");
+ RDEBUG2("Issuing AP Challenge");
/*
* The LEAP packet also contains the user name.
/*
* compose the LEAP reply packet in the EAP reply typedata
*/
-int eapleap_compose(EAP_DS *eap_ds, leap_packet_t *reply)
+int eapleap_compose(REQUEST *request, EAP_DS *eap_ds, leap_packet_t *reply)
{
leap_packet_raw_t *data;
eap_ds->request->type.num = PW_EAP_LEAP;
eap_ds->request->type.length = reply->length;
- eap_ds->request->type.data = talloc_array(eap_ds->request,
- uint8_t,
- reply->length);
+ eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t, reply->length);
if (!eap_ds->request->type.data) {
return 0;
}
+
data = (leap_packet_raw_t *) eap_ds->request->type.data;
data->version = 0x01;
data->unused = 0;
* N bytes of the challenge, followed by the user name.
*/
memcpy(&data->challenge[0], reply->challenge, reply->count);
- memcpy(&data->challenge[reply->count],
- reply->name, reply->name_len);
+ memcpy(&data->challenge[reply->count], reply->name, reply->name_len);
break;
/*
break;
default:
- ERROR("rlm_eap_leap: Internal sanity check failed");
+ REDEBUG("Internal sanity check failed");
return 0;
break;
}
*/
static int leap_initiate(UNUSED void *instance, eap_handler_t *handler)
{
+ REQUEST *request = handler->request;
leap_session_t *session;
leap_packet_t *reply;
- DEBUG2(" rlm_eap_leap: Stage 2");
+ RDEBUG2("Stage 2");
/*
* LEAP requires a User-Name attribute
*/
if (!handler->request->username) {
- DEBUG2(" rlm_eap_leap: User-Name is required for EAP-LEAP authentication.");
+ REDEBUG("User-Name is required for EAP-LEAP authentication");
return 0;
}
- reply = eapleap_initiate(handler->eap_ds, handler->request->username);
- if (!reply)
+ reply = eapleap_initiate(request, handler->eap_ds, handler->request->username);
+ if (!reply) {
return 0;
+ }
- eapleap_compose(handler->eap_ds, reply);
+ eapleap_compose(request, handler->eap_ds, reply);
handler->opaque = session = talloc(handler, leap_session_t);
if (!handler->opaque) {
session->stage = 4; /* the next stage we're in */
memcpy(session->peer_challenge, reply->challenge, reply->count);
- DEBUG2(" rlm_eap_leap: Successfully initiated");
+ REDEBUG2("Successfully initiated");
/*
* The next stage to process the packet.
static int mod_authenticate(UNUSED void *instance, eap_handler_t *handler)
{
int rcode;
+ REQUEST *request = handler->request;
leap_session_t *session;
leap_packet_t *packet;
leap_packet_t *reply;
VALUE_PAIR *password;
if (!handler->opaque) {
- ERROR("rlm_eap_leap: Cannot authenticate without LEAP history");
+ REDEBUG("Cannot authenticate without LEAP history");
return 0;
}
session = (leap_session_t *) handler->opaque;
/*
* Extract the LEAP packet.
*/
- if (!(packet = eapleap_extract(handler->eap_ds)))
+ if (!(packet = eapleap_extract(request, handler->eap_ds))) {
return 0;
+ }
/*
* The password is never sent over the wire.
* Always get the configured password, for each user.
*/
password = pairfind(handler->request->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY);
- if (!password) password = pairfind(handler->request->config_items, PW_NT_PASSWORD, 0, TAG_ANY);
if (!password) {
- DEBUG2("rlm_eap_leap: No Cleartext-Password or NT-Password configured for this user");
+ password = pairfind(handler->request->config_items, PW_NT_PASSWORD, 0, TAG_ANY);
+ }
+
+ if (!password) {
+ REDEBUG("No Cleartext-Password or NT-Password configured for this user");
talloc_free(packet);
return 0;
}
*/
switch (session->stage) {
case 4: /* Verify NtChallengeResponse */
- DEBUG2(" rlm_eap_leap: Stage 4");
- rcode = eapleap_stage4(packet, password, session);
+ RDEBUG2("Stage 4");
+ rcode = eapleap_stage4(request, packet, password, session);
session->stage = 6;
/*
return 1;
case 6: /* Issue session key */
- DEBUG2(" rlm_eap_leap: Stage 6");
- reply = eapleap_stage6(packet, handler->request,
- handler->request->username, password,
- session);
+ RDEBUG2("Stage 6");
+ reply = eapleap_stage6(request, packet, handler->request->username, password, session);
break;
/*
* Stage 2 is handled by initiate()
*/
default:
- ERROR(" rlm_eap_leap: Internal sanity check failed on stage");
+ RDEBUG("Internal sanity check failed on stage");
break;
}
return 0;
}
- eapleap_compose(handler->eap_ds, reply);
+ eapleap_compose(request, handler->eap_ds, reply);
talloc_free(reply);
return 1;
}