📄 eap_ttls.c
字号:
{ if (data->phase2_priv && data->phase2_method) { data->phase2_method->reset(sm, data->phase2_priv); data->phase2_method = NULL; data->phase2_priv = NULL; } data->phase2_method = eap_sm_get_eap_methods(EAP_VENDOR_IETF, eap_type); if (!data->phase2_method) return -1; sm->init_phase2 = 1; data->phase2_priv = data->phase2_method->init(sm); sm->init_phase2 = 0; return 0;}static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm, struct eap_ttls_data *data, u8 *in_data, size_t in_len){ u8 next_type = EAP_TYPE_NONE; struct eap_hdr *hdr; u8 *pos; size_t left; const struct eap_method *m = data->phase2_method; void *priv = data->phase2_priv; if (data->phase2_priv == NULL) { wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: %s - Phase2 not " "initialized?!", __func__); return; } hdr = (struct eap_hdr *) in_data; pos = (u8 *) (hdr + 1); left = in_len - sizeof(*hdr); if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { wpa_hexdump(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 type Nak'ed; " "allowed types", pos + 1, left - 1); eap_sm_process_nak(sm, pos + 1, left - 1); if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && sm->user->methods[sm->user_eap_method_index].method != EAP_TYPE_NONE) { next_type = sm->user->methods[ sm->user_eap_method_index++].method; wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type); eap_ttls_phase2_eap_init(sm, data, next_type); } else { eap_ttls_state(data, FAILURE); } return; } if (m->check(sm, priv, in_data, in_len)) { wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 check() asked to " "ignore the packet"); return; } m->process(sm, priv, in_data, in_len); if (!m->isDone(sm, priv)) return; if (!m->isSuccess(sm, priv)) { wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method failed"); eap_ttls_state(data, FAILURE); return; } switch (data->state) { case PHASE2_START: if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { wpa_hexdump_ascii(MSG_DEBUG, "EAP_TTLS: Phase2 " "Identity not found in the user " "database", sm->identity, sm->identity_len); eap_ttls_state(data, FAILURE); break; } eap_ttls_state(data, PHASE2_METHOD); next_type = sm->user->methods[0].method; sm->user_eap_method_index = 1; wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type); break; case PHASE2_METHOD: if (data->ttls_version > 0) { if (m->getKey) { u8 *key; size_t key_len; key = m->getKey(sm, priv, &key_len); eap_ttls_ia_permute_inner_secret(sm, data, key, key_len); } eap_ttls_state(data, PHASE_FINISHED); } else eap_ttls_state(data, SUCCESS); break; case FAILURE: break; default: wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d", __func__, data->state); break; } eap_ttls_phase2_eap_init(sm, data, next_type);}static void eap_ttls_process_phase2_eap(struct eap_sm *sm, struct eap_ttls_data *data, const u8 *eap, size_t eap_len){ struct eap_hdr *hdr; size_t len; if (data->state == PHASE2_START) { wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: initializing Phase 2"); if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_IDENTITY) < 0) { wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: failed to " "initialize EAP-Identity"); return; } } if (eap_len < sizeof(*hdr)) { wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: too short Phase 2 EAP " "packet (len=%lu)", (unsigned long) eap_len); return; } hdr = (struct eap_hdr *) eap; len = be_to_host16(hdr->length); wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: received Phase 2 EAP: code=%d " "identifier=%d length=%lu", hdr->code, hdr->identifier, (unsigned long) len); if (len > eap_len) { wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Length mismatch in Phase 2" " EAP frame (hdr len=%lu, data len in AVP=%lu)", (unsigned long) len, (unsigned long) eap_len); return; } switch (hdr->code) { case EAP_CODE_RESPONSE: eap_ttls_process_phase2_eap_response(sm, data, (u8 *) hdr, len); break; default: wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Unexpected code=%d in " "Phase 2 EAP header", hdr->code); break; }}static void eap_ttls_process_phase2(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_hdr *resp, u8 *in_data, size_t in_len){ u8 *in_decrypted; int buf_len, len_decrypted, res; struct eap_ttls_avp parse; wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" " Phase 2", (unsigned long) in_len); res = eap_tls_data_reassemble(sm, &data->ssl, &in_data, &in_len); if (res < 0 || res == 1) return; buf_len = in_len; if (data->ssl.tls_in_total > buf_len) buf_len = data->ssl.tls_in_total; in_decrypted = malloc(buf_len); if (in_decrypted == NULL) { free(data->ssl.tls_in); data->ssl.tls_in = NULL; data->ssl.tls_in_len = 0; wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory " "for decryption"); return; } len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, in_data, in_len, in_decrypted, buf_len); free(data->ssl.tls_in); data->ssl.tls_in = NULL; data->ssl.tls_in_len = 0; if (len_decrypted < 0) { wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 " "data"); free(in_decrypted); eap_ttls_state(data, FAILURE); return; } if (data->state == PHASE_FINISHED) { if (len_decrypted == 0 && tls_connection_ia_final_phase_finished(sm->ssl_ctx, data->ssl.conn)) { wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished " "received"); eap_ttls_state(data, SUCCESS); } else { wpa_printf(MSG_INFO, "EAP-TTLS: Did not receive valid " "FinalPhaseFinished"); eap_ttls_state(data, FAILURE); } free(in_decrypted); return; } wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP", in_decrypted, len_decrypted); if (eap_ttls_avp_parse(in_decrypted, len_decrypted, &parse) < 0) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs"); free(in_decrypted); eap_ttls_state(data, FAILURE); return; } if (parse.user_name) { free(sm->identity); sm->identity = malloc(parse.user_name_len); if (sm->identity) { memcpy(sm->identity, parse.user_name, parse.user_name_len); sm->identity_len = parse.user_name_len; } if (eap_user_get(sm, parse.user_name, parse.user_name_len, 1) != 0) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 Identity not " "found in the user database"); eap_ttls_state(data, FAILURE); goto done; } } if (parse.eap) { eap_ttls_process_phase2_eap(sm, data, parse.eap, parse.eap_len); } else if (parse.user_password) { eap_ttls_process_phase2_pap(sm, data, parse.user_password, parse.user_password_len); } else if (parse.chap_password) { eap_ttls_process_phase2_chap(sm, data, parse.chap_challenge, parse.chap_challenge_len, parse.chap_password, parse.chap_password_len); } else if (parse.mschap_response) { eap_ttls_process_phase2_mschap(sm, data, parse.mschap_challenge, parse.mschap_challenge_len, parse.mschap_response, parse.mschap_response_len); } else if (parse.mschap2_response) { eap_ttls_process_phase2_mschapv2(sm, data, parse.mschap_challenge, parse.mschap_challenge_len, parse.mschap2_response, parse.mschap2_response_len); }done: free(in_decrypted); free(parse.eap); }static void eap_ttls_process(struct eap_sm *sm, void *priv, u8 *respData, size_t respDataLen){ struct eap_ttls_data *data = priv; struct eap_hdr *resp; u8 *pos, flags; int left; unsigned int tls_msg_len; int peer_version; resp = (struct eap_hdr *) respData; pos = (u8 *) (resp + 1); pos++; flags = *pos++; left = htons(resp->length) - sizeof(struct eap_hdr) - 2; wpa_printf(MSG_DEBUG, "EAP-TTLS: Received packet(len=%lu) - " "Flags 0x%02x", (unsigned long) respDataLen, flags); peer_version = flags & EAP_PEAP_VERSION_MASK; if (peer_version < data->ttls_version) { wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; " "use version %d", peer_version, data->ttls_version, peer_version); data->ttls_version = peer_version; } if (data->ttls_version > 0 && !data->tls_ia_configured) { if (tls_connection_set_ia(sm->ssl_ctx, data->ssl.conn, 1)) { wpa_printf(MSG_INFO, "EAP-TTLS: Failed to enable " "TLS/IA"); eap_ttls_state(data, FAILURE); return; } data->tls_ia_configured = 1; } if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { if (left < 4) { wpa_printf(MSG_INFO, "EAP-TTLS: Short frame with TLS " "length"); eap_ttls_state(data, FAILURE); return; } tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | pos[3]; wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS Message Length: %d", tls_msg_len); if (data->ssl.tls_in_left == 0) { data->ssl.tls_in_total = tls_msg_len; data->ssl.tls_in_left = tls_msg_len; free(data->ssl.tls_in); data->ssl.tls_in = NULL; data->ssl.tls_in_len = 0; } pos += 4; left -= 4; } switch (data->state) { case PHASE1: if (eap_tls_process_helper(sm, &data->ssl, pos, left) < 0) { wpa_printf(MSG_INFO, "EAP-TTLS: TLS processing " "failed"); eap_ttls_state(data, FAILURE); } break; case PHASE2_START: case PHASE2_METHOD: case PHASE_FINISHED: eap_ttls_process_phase2(sm, data, resp, pos, left); break; case PHASE2_MSCHAPV2_RESP: if (data->mschapv2_resp_ok && left == 0) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer " "acknowledged response"); eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED : SUCCESS); } else if (!data->mschapv2_resp_ok) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer " "acknowledged error"); eap_ttls_state(data, FAILURE); } else { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected " "frame from peer (payload len %d, expected " "empty frame)", left); eap_ttls_state(data, FAILURE); } break; default: wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s", data->state, __func__); break; } if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) { wpa_printf(MSG_INFO, "EAP-TTLS: Locally detected fatal error " "in TLS processing"); eap_ttls_state(data, FAILURE); }}static Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv){ struct eap_ttls_data *data = priv; return data->state == SUCCESS || data->state == FAILURE;}static u8 * eap_ttls_v1_derive_key(struct eap_sm *sm, struct eap_ttls_data *data){ struct tls_keys keys; u8 *rnd, *key; memset(&keys, 0, sizeof(keys)); if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || keys.client_random == NULL || keys.server_random == NULL || keys.inner_secret == NULL) { wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " "client random, or server random to derive keying " "material"); return NULL; } rnd = malloc(keys.client_random_len + keys.server_random_len); key = malloc(EAP_TLS_KEY_LEN); if (rnd == NULL || key == NULL) { wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation"); free(rnd); free(key); return NULL; } memcpy(rnd, keys.client_random, keys.client_random_len); memcpy(rnd + keys.client_random_len, keys.server_random, keys.server_random_len); if (tls_prf(keys.inner_secret, keys.inner_secret_len, "ttls v1 keying material", rnd, keys.client_random_len + keys.server_random_len, key, EAP_TLS_KEY_LEN)) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key"); free(rnd); free(key); return NULL; } wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random", rnd, keys.client_random_len + keys.server_random_len); wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret", keys.inner_secret, keys.inner_secret_len); free(rnd); return key;}static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len){ struct eap_ttls_data *data = priv; u8 *eapKeyData; if (data->state != SUCCESS) return NULL; if (data->ttls_version == 0) { eapKeyData = eap_tls_derive_key(sm, &data->ssl, "ttls keying material", EAP_TLS_KEY_LEN); } else { eapKeyData = eap_ttls_v1_derive_key(sm, data); } if (eapKeyData) { *len = EAP_TLS_KEY_LEN; wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key", eapKeyData, EAP_TLS_KEY_LEN); } else { wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key"); } return eapKeyData;}static Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv){ struct eap_ttls_data *data = priv; return data->state == SUCCESS;}int eap_server_ttls_register(void){ struct eap_method *eap; int ret; eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS"); if (eap == NULL) return -1; eap->init = eap_ttls_init; eap->reset = eap_ttls_reset; eap->buildReq = eap_ttls_buildReq; eap->check = eap_ttls_check; eap->process = eap_ttls_process; eap->isDone = eap_ttls_isDone; eap->getKey = eap_ttls_getKey; eap->isSuccess = eap_ttls_isSuccess; ret = eap_server_method_register(eap); if (ret) eap_server_method_free(eap); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -