static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const struct wpabuf *reqData) { struct eap_leap_data *data = priv; struct wpabuf *resp; const u8 *pos, *challenge, *identity, *password; u8 challenge_len, *rpos; size_t identity_len, password_len, len; int pwhash; wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request"); identity = eap_get_config_identity(sm, &identity_len); password = eap_get_config_password2(sm, &password_len, &pwhash); if (identity == NULL || password == NULL) return NULL; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len); if (pos == NULL || len < 3) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame"); ret->ignore = TRUE; return NULL; } if (*pos != LEAP_VERSION) { wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " "%d", *pos); ret->ignore = TRUE; return NULL; } pos++; pos++; /* skip unused byte */ challenge_len = *pos++; if (challenge_len != LEAP_CHALLENGE_LEN || challenge_len > len - 3) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge " "(challenge_len=%d reqDataLen=%lu)", challenge_len, (unsigned long) wpabuf_len(reqData)); ret->ignore = TRUE; return NULL; } challenge = pos; os_memcpy(data->peer_challenge, challenge, LEAP_CHALLENGE_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge from AP", challenge, LEAP_CHALLENGE_LEN); wpa_printf(MSG_DEBUG, "EAP-LEAP: Generating Challenge Response"); resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP, 3 + LEAP_RESPONSE_LEN + identity_len, EAP_CODE_RESPONSE, eap_get_id(reqData)); if (resp == NULL) return NULL; wpabuf_put_u8(resp, LEAP_VERSION); wpabuf_put_u8(resp, 0); /* unused */ wpabuf_put_u8(resp, LEAP_RESPONSE_LEN); rpos = wpabuf_put(resp, LEAP_RESPONSE_LEN); if (pwhash) challenge_response(challenge, password, rpos); else nt_challenge_response(challenge, password, password_len, rpos); os_memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response", rpos, LEAP_RESPONSE_LEN); wpabuf_put_data(resp, identity, identity_len); data->state = LEAP_WAIT_SUCCESS; return resp; }
static u8 * eap_leap_process_request(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const u8 *reqData, size_t reqDataLen, size_t *respDataLen) { struct eap_leap_data *data = priv; struct wpa_ssid *config = eap_get_config(sm); const struct eap_hdr *req; struct eap_hdr *resp; const u8 *pos, *challenge; u8 challenge_len, *rpos; wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request"); req = (const struct eap_hdr *) reqData; pos = (const u8 *) (req + 1); if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_LEAP) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame"); ret->ignore = TRUE; return NULL; } pos++; if (*pos != LEAP_VERSION) { wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " "%d", *pos); ret->ignore = TRUE; return NULL; } pos++; pos++; /* skip unused byte */ challenge_len = *pos++; if (challenge_len != LEAP_CHALLENGE_LEN || challenge_len > reqDataLen - sizeof(*req) - 4) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge " "(challenge_len=%d reqDataLen=%lu", challenge_len, (unsigned long) reqDataLen); ret->ignore = TRUE; return NULL; } challenge = pos; memcpy(data->peer_challenge, challenge, LEAP_CHALLENGE_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge from AP", challenge, LEAP_CHALLENGE_LEN); wpa_printf(MSG_DEBUG, "EAP-LEAP: Generating Challenge Response"); *respDataLen = sizeof(struct eap_hdr) + 1 + 3 + LEAP_RESPONSE_LEN + config->identity_len; resp = malloc(*respDataLen); if (resp == NULL) return NULL; resp->code = EAP_CODE_RESPONSE; resp->identifier = req->identifier; resp->length = host_to_be16(*respDataLen); rpos = (u8 *) (resp + 1); *rpos++ = EAP_TYPE_LEAP; *rpos++ = LEAP_VERSION; *rpos++ = 0; /* unused */ *rpos++ = LEAP_RESPONSE_LEN; nt_challenge_response(challenge, config->password, config->password_len, rpos); memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response", rpos, LEAP_RESPONSE_LEN); rpos += LEAP_RESPONSE_LEN; memcpy(rpos, config->identity, config->identity_len); data->state = LEAP_WAIT_SUCCESS; return (u8 *) resp; }
static u8 * eap_leap_process_request(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const u8 *reqData, size_t reqDataLen, size_t *respDataLen) { struct eap_leap_data *data = priv; const struct eap_hdr *req; struct eap_hdr *resp; const u8 *pos, *challenge, *identity, *password; u8 challenge_len, *rpos; size_t identity_len, password_len; wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request"); identity = eap_get_config_identity(sm, &identity_len); password = eap_get_config_password(sm, &password_len); if (identity == NULL || password == NULL) return NULL; req = (const struct eap_hdr *) reqData; pos = (const u8 *) (req + 1); if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_LEAP) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame"); ret->ignore = TRUE; return NULL; } pos++; if (*pos != LEAP_VERSION) { wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " "%d", *pos); ret->ignore = TRUE; return NULL; } pos++; pos++; /* skip unused byte */ challenge_len = *pos++; if (challenge_len != LEAP_CHALLENGE_LEN || challenge_len > reqDataLen - sizeof(*req) - 4) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge " "(challenge_len=%d reqDataLen=%lu)", challenge_len, (unsigned long) reqDataLen); ret->ignore = TRUE; return NULL; } challenge = pos; os_memcpy(data->peer_challenge, challenge, LEAP_CHALLENGE_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge from AP", challenge, LEAP_CHALLENGE_LEN); wpa_printf(MSG_DEBUG, "EAP-LEAP: Generating Challenge Response"); resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP, respDataLen, 3 + LEAP_RESPONSE_LEN + identity_len, EAP_CODE_RESPONSE, req->identifier, &rpos); if (resp == NULL) return NULL; *rpos++ = LEAP_VERSION; *rpos++ = 0; /* unused */ *rpos++ = LEAP_RESPONSE_LEN; nt_challenge_response(challenge, password, password_len, rpos); os_memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response", rpos, LEAP_RESPONSE_LEN); rpos += LEAP_RESPONSE_LEN; os_memcpy(rpos, identity, identity_len); data->state = LEAP_WAIT_SUCCESS; return (u8 *) resp; }
static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, u8 **resp, size_t *resp_len) { struct wpa_ssid *config = eap_get_config(sm); u8 *buf, *pos, *challenge; wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request"); pos = buf = os_malloc(config->identity_len + 1000); if (buf == NULL) { wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to allocate memory"); return -1; } /* User-Name */ pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, config->identity, config->identity_len); /* MS-CHAP-Challenge */ challenge = eap_ttls_implicit_challenge( sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); if (challenge == NULL) { os_free(buf); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive " "implicit challenge"); return -1; } pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, RADIUS_VENDOR_ID_MICROSOFT, 1, challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); /* MS-CHAP-Response */ pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE, RADIUS_VENDOR_ID_MICROSOFT, 1, EAP_TTLS_MSCHAP_RESPONSE_LEN); data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN]; *pos++ = data->ident; *pos++ = 1; /* Flags: Use NT style passwords */ os_memset(pos, 0, 24); /* LM-Response */ pos += 24; nt_challenge_response(challenge, config->password, config->password_len, pos); /* NT-Response */ wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password", config->password, config->password_len); wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge", challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24); pos += 24; os_free(challenge); AVP_PAD(buf, pos); *resp = buf; *resp_len = pos - buf; if (data->ttls_version > 0) { /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success, * so do not allow connection to be terminated yet. */ ret->methodState = METHOD_CONT; ret->decision = DECISION_COND_SUCC; } else { /* EAP-TTLS/MSCHAP does not provide tunneled success * notification, so assume that Phase2 succeeds. */ ret->methodState = METHOD_DONE; ret->decision = DECISION_COND_SUCC; } return 0; }