📄 eap_ttls.c
字号:
return 0;}#if EAP_TTLS_VERSION > 0static void eap_ttls_final_phase_finished(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, u8 identifier, struct wpabuf **out_data){ wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished received"); wpa_printf(MSG_INFO, "EAP-TTLS: TLS/IA authentication succeeded"); ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; data->phase2_success = 1; *out_data = eap_ttls_build_phase_finished(sm, data, identifier, 1); eap_ttls_v1_derive_key(sm, data);}#endif /* EAP_TTLS_VERSION */static int eap_ttls_implicit_identity_request(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, u8 identifier, struct wpabuf **out_data){ int retval = 0; struct eap_hdr *hdr; struct wpabuf *resp; hdr = (struct eap_hdr *) eap_ttls_fake_identity_request(); if (hdr == NULL) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return -1; } resp = NULL; if (eap_ttls_phase2_request(sm, data, ret, hdr, &resp)) { wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request " "processing failed"); retval = -1; } else { retval = eap_ttls_encrypt_response(sm, data, resp, identifier, out_data); } os_free(hdr); if (retval < 0) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; } return retval;}static int eap_ttls_phase2_start(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, u8 identifier, struct wpabuf **out_data){ data->phase2_start = 0; /* * EAP-TTLS does not use Phase2 on fast re-auth; this must be done only * if TLS part was indeed resuming a previous session. Most * Authentication Servers terminate EAP-TTLS before reaching this * point, but some do not. Make wpa_supplicant stop phase 2 here, if * needed. */ if (data->reauth && tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - " "skip phase 2"); *out_data = eap_peer_tls_build_ack(identifier, EAP_TYPE_TTLS, data->ttls_version); ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; data->phase2_success = 1; return 0; } return eap_ttls_implicit_identity_request(sm, data, ret, identifier, out_data);}static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, u8 identifier, const struct wpabuf *in_data, struct wpabuf **out_data){ struct wpabuf *in_decrypted = NULL; int retval = 0; struct ttls_parse_avp parse; os_memset(&parse, 0, sizeof(parse)); wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" " Phase 2", in_data ? (unsigned long) wpabuf_len(in_data) : 0); if (data->pending_phase2_req) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - " "skip decryption and use old data"); /* Clear TLS reassembly state. */ eap_peer_tls_reset_input(&data->ssl); in_decrypted = data->pending_phase2_req; data->pending_phase2_req = NULL; if (wpabuf_len(in_decrypted) == 0) { wpabuf_free(in_decrypted); return eap_ttls_implicit_identity_request( sm, data, ret, identifier, out_data); } goto continue_req; } if ((in_data == NULL || wpabuf_len(in_data) == 0) && data->phase2_start) { return eap_ttls_phase2_start(sm, data, ret, identifier, out_data); } if (in_data == NULL || wpabuf_len(in_data) == 0) { /* Received TLS ACK - requesting more fragments */ return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS, data->ttls_version, identifier, NULL, out_data); } retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); if (retval) goto done;#if EAP_TTLS_VERSION > 0 if (data->ttls_version > 0 && (in_decrypted == NULL || wpabuf_len(in_decrypted) == 0) && tls_connection_ia_final_phase_finished(sm->ssl_ctx, data->ssl.conn)) { eap_ttls_final_phase_finished(sm, data, ret, identifier, out_data); goto done; }#endif /* EAP_TTLS_VERSION */continue_req: data->phase2_start = 0; if (eap_ttls_parse_avps(in_decrypted, &parse) < 0) { retval = -1; goto done; } retval = eap_ttls_process_decrypted(sm, data, ret, identifier, &parse, in_decrypted, out_data);done: wpabuf_free(in_decrypted); os_free(parse.eapdata); if (retval < 0) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; } return retval;}static int eap_ttls_process_start(struct eap_sm *sm, struct eap_ttls_data *data, u8 flags, struct eap_method_ret *ret){ struct eap_peer_config *config = eap_get_config(sm); wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own ver=%d)", flags & EAP_PEAP_VERSION_MASK, data->ttls_version);#if EAP_TTLS_VERSION > 0 if ((flags & EAP_PEAP_VERSION_MASK) < data->ttls_version) data->ttls_version = flags & EAP_PEAP_VERSION_MASK; if (data->force_ttls_version >= 0 && data->force_ttls_version != data->ttls_version) { wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to select " "forced TTLS version %d", data->force_ttls_version); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; ret->allowNotifications = FALSE; return -1; } wpa_printf(MSG_DEBUG, "EAP-TTLS: Using TTLS version %d", data->ttls_version); if (data->ttls_version > 0) data->ssl.tls_ia = 1;#endif /* EAP_TTLS_VERSION */ if (!data->ssl_initialized && eap_peer_tls_ssl_init(sm, &data->ssl, config)) { wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL."); return -1; } data->ssl_initialized = 1; wpa_printf(MSG_DEBUG, "EAP-TTLS: Start"); return 0;}static int eap_ttls_process_handshake(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, u8 identifier, const u8 *in_data, size_t in_len, struct wpabuf **out_data){ int res; res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, data->ttls_version, identifier, in_data, in_len, out_data); if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to " "Phase 2"); if (data->resuming) { wpa_printf(MSG_DEBUG, "EAP-TTLS: fast reauth - may " "skip Phase 2"); ret->decision = DECISION_COND_SUCC; ret->methodState = METHOD_MAY_CONT; } data->phase2_start = 1; if (data->ttls_version == 0) eap_ttls_v0_derive_key(sm, data); if (*out_data == NULL || wpabuf_len(*out_data) == 0) { if (eap_ttls_decrypt(sm, data, ret, identifier, NULL, out_data)) { wpa_printf(MSG_WARNING, "EAP-TTLS: " "failed to process early " "start for Phase 2"); } res = 0; } data->resuming = 0; } if (res == 2) { struct wpabuf msg; /* * Application data included in the handshake message. */ wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = *out_data; *out_data = NULL; wpabuf_set(&msg, in_data, in_len); res = eap_ttls_decrypt(sm, data, ret, identifier, &msg, out_data); } return res;}static void eap_ttls_check_auth_status(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret){ if (data->ttls_version == 0 && ret->methodState == METHOD_DONE) { ret->allowNotifications = FALSE; if (ret->decision == DECISION_UNCOND_SUCC || ret->decision == DECISION_COND_SUCC) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " "completed successfully"); data->phase2_success = 1;#ifdef EAP_TNC if (!data->ready_for_tnc && !data->tnc_started) { /* * TNC may be required as the next * authentication method within the tunnel. */ ret->methodState = METHOD_MAY_CONT; data->ready_for_tnc = 1; }#endif /* EAP_TNC */ } } else if (data->ttls_version == 0 && ret->methodState == METHOD_MAY_CONT && (ret->decision == DECISION_UNCOND_SUCC || ret->decision == DECISION_COND_SUCC)) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " "completed successfully (MAY_CONT)"); data->phase2_success = 1; }}static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const struct wpabuf *reqData){ size_t left; int res; u8 flags, id; struct wpabuf *resp; const u8 *pos; struct eap_ttls_data *data = priv; pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret, reqData, &left, &flags); if (pos == NULL) return NULL; id = eap_get_id(reqData); if (flags & EAP_TLS_FLAGS_START) { if (eap_ttls_process_start(sm, data, flags, ret) < 0) return NULL; /* RFC 5281, Ch. 9.2: * "This packet MAY contain additional information in the form * of AVPs, which may provide useful hints to the client" * For now, ignore any potential extra data. */ left = 0; } else if (!data->ssl_initialized) { wpa_printf(MSG_DEBUG, "EAP-TTLS: First message did not " "include Start flag"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; ret->allowNotifications = FALSE; return NULL; } resp = NULL; if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && !data->resuming) { struct wpabuf msg; wpabuf_set(&msg, pos, left); res = eap_ttls_decrypt(sm, data, ret, id, &msg, &resp); } else { res = eap_ttls_process_handshake(sm, data, ret, id, pos, left, &resp); } eap_ttls_check_auth_status(sm, data, ret); /* FIX: what about res == -1? Could just move all error processing into * the other functions and get rid of this res==1 case here. */ if (res == 1) { wpabuf_free(resp); return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS, data->ttls_version); } return resp;}static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv){ struct eap_ttls_data *data = priv; return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && data->phase2_success;}static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv){ struct eap_ttls_data *data = priv; wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = NULL;#ifdef EAP_TNC data->ready_for_tnc = 0; data->tnc_started = 0;#endif /* EAP_TNC */}static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv){ struct eap_ttls_data *data = priv; os_free(data->key_data); data->key_data = NULL; if (eap_peer_tls_reauth_init(sm, &data->ssl)) { os_free(data); return NULL; } if (data->phase2_priv && data->phase2_method && data->phase2_method->init_for_reauth) data->phase2_method->init_for_reauth(sm, data->phase2_priv); data->phase2_start = 0; data->phase2_success = 0; data->resuming = 1; data->reauth = 1; return priv;}static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf, size_t buflen, int verbose){ struct eap_ttls_data *data = priv; int len, ret; len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); ret = os_snprintf(buf + len, buflen - len, "EAP-TTLSv%d Phase2 method=", data->ttls_version); if (ret < 0 || (size_t) ret >= buflen - len) return len; len += ret; switch (data->phase2_type) { case EAP_TTLS_PHASE2_EAP: ret = os_snprintf(buf + len, buflen - len, "EAP-%s\n", data->phase2_method ? data->phase2_method->name : "?"); break; case EAP_TTLS_PHASE2_MSCHAPV2: ret = os_snprintf(buf + len, buflen - len, "MSCHAPV2\n"); break; case EAP_TTLS_PHASE2_MSCHAP: ret = os_snprintf(buf + len, buflen - len, "MSCHAP\n"); break; case EAP_TTLS_PHASE2_PAP: ret = os_snprintf(buf + len, buflen - len, "PAP\n"); break; case EAP_TTLS_PHASE2_CHAP: ret = os_snprintf(buf + len, buflen - len, "CHAP\n"); break; default: ret = 0; break; } if (ret < 0 || (size_t) ret >= buflen - len) return len; len += ret; return len;}static Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv){ struct eap_ttls_data *data = priv; return data->key_data != NULL && data->phase2_success;}static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len){ struct eap_ttls_data *data = priv; u8 *key; if (data->key_data == NULL || !data->phase2_success) return NULL; key = os_malloc(EAP_TLS_KEY_LEN); if (key == NULL) return NULL; *len = EAP_TLS_KEY_LEN; os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); return key;}int eap_peer_ttls_register(void){ struct eap_method *eap; int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS"); if (eap == NULL) return -1; eap->init = eap_ttls_init; eap->deinit = eap_ttls_deinit; eap->process = eap_ttls_process; eap->isKeyAvailable = eap_ttls_isKeyAvailable; eap->getKey = eap_ttls_getKey; eap->get_status = eap_ttls_get_status; eap->has_reauth_data = eap_ttls_has_reauth_data; eap->deinit_for_reauth = eap_ttls_deinit_for_reauth; eap->init_for_reauth = eap_ttls_init_for_reauth; ret = eap_peer_method_register(eap); if (ret) eap_peer_method_free(eap); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -