📄 eap.c
字号:
} else { identity = config->identity; identity_len = config->identity_len; wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity", identity, identity_len); } if (identity == NULL) { wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity " "configuration was not available"); if (config->pcsc) { if (eap_sm_get_scard_identity(sm, config) < 0) return NULL; identity = config->identity; identity_len = config->identity_len; wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from " "IMSI", identity, identity_len); } else { eap_sm_request_identity(sm, config); return NULL; } } *len = sizeof(struct eap_hdr) + 1 + identity_len; resp = malloc(*len); if (resp == NULL) return NULL; resp->code = EAP_CODE_RESPONSE; resp->identifier = id; resp->length = host_to_be16(*len); pos = (u8 *) (resp + 1); *pos++ = EAP_TYPE_IDENTITY; memcpy(pos, identity, identity_len); return (u8 *) resp;}static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req, size_t len){ const struct eap_hdr *hdr = (const struct eap_hdr *) req; const u8 *pos; char *msg; size_t msg_len; int i; pos = (const u8 *) (hdr + 1); pos++; msg_len = be_to_host16(hdr->length); if (msg_len < 5) return; msg_len -= 5; wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data", pos, msg_len); msg = malloc(msg_len + 1); if (msg == NULL) return; for (i = 0; i < msg_len; i++) msg[i] = isprint(pos[i]) ? (char) pos[i] : '_'; msg[msg_len] = '\0'; wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s", WPA_EVENT_EAP_NOTIFICATION, msg); free(msg);}static u8 * eap_sm_buildNotify(struct eap_sm *sm, int id, size_t *len){ struct eap_hdr *resp; u8 *pos; wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification"); *len = sizeof(struct eap_hdr) + 1; resp = malloc(*len); if (resp == NULL) return NULL; resp->code = EAP_CODE_RESPONSE; resp->identifier = id; resp->length = host_to_be16(*len); pos = (u8 *) (resp + 1); *pos = EAP_TYPE_NOTIFICATION; return (u8 *) resp;}static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len){ const struct eap_hdr *hdr; size_t plen; sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE; sm->reqId = 0; sm->reqMethod = EAP_TYPE_NONE; if (req == NULL || len < sizeof(*hdr)) return; hdr = (const struct eap_hdr *) req; plen = be_to_host16(hdr->length); if (plen > len) { wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet " "(len=%lu plen=%lu)", (unsigned long) len, (unsigned long) plen); return; } sm->reqId = hdr->identifier; if (sm->workaround) { md5_vector(1, (const u8 **) &req, &len, sm->req_md5); } switch (hdr->code) { case EAP_CODE_REQUEST: sm->rxReq = TRUE; if (plen > sizeof(*hdr)) sm->reqMethod = *((u8 *) (hdr + 1)); wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request method=%d " "id=%d", sm->reqMethod, sm->reqId); break; case EAP_CODE_RESPONSE: if (sm->selectedMethod == EAP_TYPE_LEAP) { /* * LEAP differs from RFC 4137 by using reversed roles * for mutual authentication and because of this, we * need to accept EAP-Response frames if LEAP is used. */ sm->rxResp = TRUE; if (plen > sizeof(*hdr)) sm->reqMethod = *((u8 *) (hdr + 1)); wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for " "LEAP method=%d id=%d", sm->reqMethod, sm->reqId); break; } wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response"); break; case EAP_CODE_SUCCESS: wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success"); sm->rxSuccess = TRUE; break; case EAP_CODE_FAILURE: wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure"); sm->rxFailure = TRUE; break; default: wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown " "code %d", hdr->code); break; }}/** * eap_sm_init - Allocate and initialize EAP state machine * @eapol_ctx: Context data to be used with eapol_cb calls * @eapol_cb: Pointer to EAPOL callback functions * @msg_ctx: Context data for wpa_msg() calls * @conf: EAP configuration * Returns: Pointer to the allocated EAP state machine or %NULL on failure * * This function allocates and initializes an EAP state machine. In addition, * this initializes TLS library for the new EAP state machine. eapol_cb pointer * will be in use until eap_sm_deinit() is used to deinitialize this EAP state * machine. Consequently, the caller must make sure that this data structure * remains alive while the EAP state machine is active. */struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb, void *msg_ctx, struct eap_config *conf){ struct eap_sm *sm; struct tls_config tlsconf; sm = malloc(sizeof(*sm)); if (sm == NULL) return NULL; memset(sm, 0, sizeof(*sm)); sm->eapol_ctx = eapol_ctx; sm->eapol_cb = eapol_cb; sm->msg_ctx = msg_ctx; sm->ClientTimeout = 60; memset(&tlsconf, 0, sizeof(tlsconf)); tlsconf.opensc_engine_path = conf->opensc_engine_path; tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path; tlsconf.pkcs11_module_path = conf->pkcs11_module_path; sm->ssl_ctx = tls_init(&tlsconf); if (sm->ssl_ctx == NULL) { wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS " "context."); free(sm); return NULL; } return sm;}/** * eap_sm_deinit - Deinitialize and free an EAP state machine * @sm: Pointer to EAP state machine allocated with eap_sm_init() * * This function deinitializes EAP state machine and frees all allocated * resources. */void eap_sm_deinit(struct eap_sm *sm){ if (sm == NULL) return; eap_deinit_prev_method(sm, "EAP deinit"); eap_sm_abort(sm); tls_deinit(sm->ssl_ctx); free(sm);}/** * eap_sm_step - Step EAP state machine * @sm: Pointer to EAP state machine allocated with eap_sm_init() * Returns: 1 if EAP state was changed or 0 if not * * This function advances EAP state machine to a new state to match with the * current variables. This should be called whenever variables used by the EAP * state machine have changed. */int eap_sm_step(struct eap_sm *sm){ int res = 0; do { sm->changed = FALSE; SM_STEP_RUN(EAP); if (sm->changed) res = 1; } while (sm->changed); return res;}/** * eap_sm_abort - Abort EAP authentication * @sm: Pointer to EAP state machine allocated with eap_sm_init() * * Release system resources that have been allocated for the authentication * session without fully deinitializing the EAP state machine. */void eap_sm_abort(struct eap_sm *sm){ free(sm->lastRespData); sm->lastRespData = NULL; free(sm->eapRespData); sm->eapRespData = NULL; free(sm->eapKeyData); sm->eapKeyData = NULL;}static const char * eap_sm_state_txt(int state){ switch (state) { case EAP_INITIALIZE: return "INITIALIZE"; case EAP_DISABLED: return "DISABLED"; case EAP_IDLE: return "IDLE"; case EAP_RECEIVED: return "RECEIVED"; case EAP_GET_METHOD: return "GET_METHOD"; case EAP_METHOD: return "METHOD"; case EAP_SEND_RESPONSE: return "SEND_RESPONSE"; case EAP_DISCARD: return "DISCARD"; case EAP_IDENTITY: return "IDENTITY"; case EAP_NOTIFICATION: return "NOTIFICATION"; case EAP_RETRANSMIT: return "RETRANSMIT"; case EAP_SUCCESS: return "SUCCESS"; case EAP_FAILURE: return "FAILURE"; default: return "UNKNOWN"; }}static const char * eap_sm_method_state_txt(EapMethodState state){ switch (state) { case METHOD_NONE: return "NONE"; case METHOD_INIT: return "INIT"; case METHOD_CONT: return "CONT"; case METHOD_MAY_CONT: return "MAY_CONT"; case METHOD_DONE: return "DONE"; default: return "UNKNOWN"; }}static const char * eap_sm_decision_txt(EapDecision decision){ switch (decision) { case DECISION_FAIL: return "FAIL"; case DECISION_COND_SUCC: return "COND_SUCC"; case DECISION_UNCOND_SUCC: return "UNCOND_SUCC"; default: return "UNKNOWN"; }}/** * eap_sm_get_status - Get EAP state machine status * @sm: Pointer to EAP state machine allocated with eap_sm_init() * @buf: Buffer for status information * @buflen: Maximum buffer length * @verbose: Whether to include verbose status information * Returns: Number of bytes written to buf. * * Query EAP state machine for status information. This function fills in a * text area with current status information from the EAPOL state machine. If * the buffer (buf) is not large enough, status information will be truncated * to fit the buffer. */int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose){ int len; if (sm == NULL) return 0; len = snprintf(buf, buflen, "EAP state=%s\n", eap_sm_state_txt(sm->EAP_state)); if (sm->selectedMethod != EAP_TYPE_NONE) { const char *name; if (sm->m) { name = sm->m->name; } else { const struct eap_method *m = eap_sm_get_eap_methods(sm->selectedMethod); if (m) name = m->name; else name = "?"; } len += snprintf(buf + len, buflen - len, "selectedMethod=%d (EAP-%s)\n", sm->selectedMethod, name); if (sm->m && sm->m->get_status) { len += sm->m->get_status(sm, sm->eap_method_priv, buf + len, buflen - len, verbose); } } if (verbose) { len += snprintf(buf + len, buflen - len, "reqMethod=%d\n" "methodState=%s\n" "decision=%s\n" "ClientTimeout=%d\n", sm->reqMethod, eap_sm_method_state_txt(sm->methodState), eap_sm_decision_txt(sm->decision), sm->ClientTimeout); } return len;}typedef enum { TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP, TYPE_PIN, TYPE_NEW_PASSWORD, TYPE_PASSPHRASE} eap_ctrl_req_type;static void eap_sm_request(struct eap_sm *sm, struct wpa_ssid *config, eap_ctrl_req_type type, const char *msg, size_t msglen){ char *buf; size_t buflen; int len; char *field; char *txt, *tmp; if (config == NULL || sm == NULL) return; switch (type) { case TYPE_IDENTITY: field = "IDENTITY"; txt = "Identity"; config->pending_req_identity++; break; case TYPE_PASSWORD: field = "PASSWORD"; txt = "Password"; config->pending_req_password++; break; case TYPE_NEW_PASSWORD: field = "NEW_PASSWORD"; txt = "New Password"; config->pending_req_new_password++; break; case TYPE_PIN: field = "PIN"; txt = "PIN"; config->pending_req_pin++; break; case TYPE_OTP: field = "OTP"; if (msg) { tmp = malloc(msglen + 3); if (tmp == NULL) return; tmp[0] = '['; memcpy(tmp + 1, msg, msglen); tmp[msglen + 1] = ']'; tmp[msglen + 2] = '\0'; txt = tmp; free(config->pending_req_otp); config->pending_req_otp = tmp; config->pending_req_otp_len = msglen + 3; } else { if (config->pending_req_otp == NULL) return; txt = config->pending_req_otp; } break; case TYPE_PASSPHRASE: field = "PASSPHRASE"; txt = "Private key passphrase"; config->pending_req_passphrase++; break; default: return; } buflen = 100 + strlen(txt) + config->ssid_len; buf = malloc(buflen); if (buf == NULL) return; len = snprintf(buf, buflen, WPA_CTRL_REQ "%s-%d:%s needed for SSID ", field, config->id, txt); if (config->ssid && buflen > len + config->ssid_len) { memcpy(buf + len, config->ssid, config->ssid_len); len += config->ssid_len; buf[len] = '\0'; } wpa_msg(sm->msg_ctx, MSG_INFO, "%s", buf); free(buf);}/** * eap_sm_request_identity - Request identity from user (ctrl_iface) * @sm: Pointer to EAP state machine allocated with eap_sm_init() * @config: Pointer to the current network configuration * * EAP methods can call this function to request identity information for the * current network. This is normally called when the identity is not included * in the network configuration. The request will be sent to monitor programs * through the control interface.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -