⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eap.c

📁 hostapd源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			SM_ENTER(EAP, METHOD_REQUEST);		break;	case EAP_NAK:		SM_ENTER(EAP, SELECT_ACTION);		break;	case EAP_SELECT_ACTION:		if (sm->decision == DECISION_FAILURE)			SM_ENTER(EAP, FAILURE);		else if (sm->decision == DECISION_SUCCESS)			SM_ENTER(EAP, SUCCESS);		else			SM_ENTER(EAP, PROPOSE_METHOD);		break;	case EAP_TIMEOUT_FAILURE:		break;	case EAP_FAILURE:		break;	case EAP_SUCCESS:		break;	}}static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,				   int eapSRTT, int eapRTTVAR,				   int methodTimeout){	/* For now, retransmission is done in EAPOL state machines, so make	 * sure EAP state machine does not end up trying to retransmit packets.	 */	return 1;}static void eap_sm_parseEapResp(struct eap_sm *sm, u8 *resp, size_t len){	struct eap_hdr *hdr;	size_t plen;	/* parse rxResp, respId, respMethod */	sm->rxResp = FALSE;	sm->respId = -1;	sm->respMethod = EAP_TYPE_NONE;	sm->respVendor = EAP_VENDOR_IETF;	sm->respVendorMethod = EAP_TYPE_NONE;	if (resp == NULL || len < sizeof(*hdr))		return;	hdr = (struct eap_hdr *) resp;	plen = ntohs(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->respId = hdr->identifier;	if (hdr->code == EAP_CODE_RESPONSE)		sm->rxResp = TRUE;	if (plen > sizeof(*hdr)) {		u8 *pos = (u8 *) (hdr + 1);		sm->respMethod = *pos++;		if (sm->respMethod == EAP_TYPE_EXPANDED) {			if (plen < sizeof(*hdr) + 8) {				wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "					   "expanded EAP-Packet (plen=%lu)",					   (unsigned long) plen);				return;			}			sm->respVendor = WPA_GET_BE24(pos);			pos += 3;			sm->respVendorMethod = WPA_GET_BE32(pos);		}	}	wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d "		   "respMethod=%u respVendor=%u respVendorMethod=%u",		   sm->rxResp, sm->respId, sm->respMethod, sm->respVendor,		   sm->respVendorMethod);}static u8 * eap_sm_buildSuccess(struct eap_sm *sm, int id, size_t *len){	struct eap_hdr *resp;	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id);	*len = sizeof(*resp);	resp = malloc(*len);	if (resp == NULL)		return NULL;	resp->code = EAP_CODE_SUCCESS;	resp->identifier = id;	resp->length = htons(*len);	return (u8 *) resp;}static u8 * eap_sm_buildFailure(struct eap_sm *sm, int id, size_t *len){	struct eap_hdr *resp;	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id);	*len = sizeof(*resp);	resp = malloc(*len);	if (resp == NULL)		return NULL;	resp->code = EAP_CODE_FAILURE;	resp->identifier = id;	resp->length = htons(*len);	return (u8 *) resp;}static int eap_sm_nextId(struct eap_sm *sm, int id){	if (id < 0) {		/* RFC 3748 Ch 4.1: recommended to initalize Identifier with a		 * random number */		id = rand() & 0xff;		if (id != sm->lastId)			return id;	}	return (id + 1) & 0xff;}/** * eap_sm_process_nak - Process EAP-Response/Nak * @sm: Pointer to EAP state machine allocated with eap_sm_init() * @nak_list: Nak list (allowed methods) from the supplicant * @len: Length of nak_list in bytes * * This function is called when EAP-Response/Nak is received from the * supplicant. This can happen for both phase 1 and phase 2 authentications. */void eap_sm_process_nak(struct eap_sm *sm, u8 *nak_list, size_t len){	int i, j;	wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method "		   "index %d)", sm->user_eap_method_index);	wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods",		    (u8 *) sm->user->methods,		    EAP_MAX_METHODS * sizeof(sm->user->methods[0]));	wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer",		    nak_list, len);	i = sm->user_eap_method_index;	while (i < EAP_MAX_METHODS &&	       (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||		sm->user->methods[i].method != EAP_TYPE_NONE)) {		if (sm->user->methods[i].vendor != EAP_VENDOR_IETF)			goto not_found;		for (j = 0; j < len; j++) {			if (nak_list[j] == sm->user->methods[i].method) {				break;			}		}		if (j < len) {			/* found */			i++;			continue;		}	not_found:		/* not found - remove from the list */		memmove(&sm->user->methods[i], &sm->user->methods[i + 1],			(EAP_MAX_METHODS - i - 1) *			sizeof(sm->user->methods[0]));		sm->user->methods[EAP_MAX_METHODS - 1].vendor =			EAP_VENDOR_IETF;		sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE;	}	wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods",		    (u8 *) sm->user->methods, EAP_MAX_METHODS *		    sizeof(sm->user->methods[0]));}static void eap_sm_Policy_update(struct eap_sm *sm, u8 *nak_list, size_t len){	if (nak_list == NULL || sm == NULL || sm->user == NULL)		return;	if (sm->user->phase2) {		wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user"			   " info was selected - reject");		sm->decision = DECISION_FAILURE;		return;	}	eap_sm_process_nak(sm, nak_list, len);}static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor){	EapType next;	int idx = sm->user_eap_method_index;	/* In theory, there should be no problems with starting	 * re-authentication with something else than EAP-Request/Identity and	 * this does indeed work with wpa_supplicant. However, at least Funk	 * Supplicant seemed to ignore re-auth if it skipped	 * EAP-Request/Identity.	 * Re-auth sets currentId == -1, so that can be used here to select	 * whether Identity needs to be requested again. */	if (sm->identity == NULL || sm->currentId == -1) {		*vendor = EAP_VENDOR_IETF;		next = EAP_TYPE_IDENTITY;		sm->update_user = TRUE;	} else if (sm->user && idx < EAP_MAX_METHODS &&		   (sm->user->methods[idx].vendor != EAP_VENDOR_IETF ||		    sm->user->methods[idx].method != EAP_TYPE_NONE)) {		*vendor = sm->user->methods[idx].vendor;		next = sm->user->methods[idx].method;		sm->user_eap_method_index++;	} else {		*vendor = EAP_VENDOR_IETF;		next = EAP_TYPE_NONE;	}	wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d",		   *vendor, next);	return next;}static int eap_sm_Policy_getDecision(struct eap_sm *sm){	if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY &&	    sm->m->isSuccess(sm, sm->eap_method_priv)) {		wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> "			   "SUCCESS");		sm->update_user = TRUE;		return DECISION_SUCCESS;	}	if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) &&	    !sm->m->isSuccess(sm, sm->eap_method_priv)) {		wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> "			   "FAILURE");		sm->update_user = TRUE;		return DECISION_FAILURE;	}	if ((sm->user == NULL || sm->update_user) && sm->identity) {		if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) {			wpa_printf(MSG_DEBUG, "EAP: getDecision: user not "				   "found from database -> FAILURE");			return DECISION_FAILURE;		}		sm->update_user = FALSE;	}	if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&	    (sm->user->methods[sm->user_eap_method_index].vendor !=	     EAP_VENDOR_IETF ||	     sm->user->methods[sm->user_eap_method_index].method !=	     EAP_TYPE_NONE)) {		wpa_printf(MSG_DEBUG, "EAP: getDecision: another method "			   "available -> CONTINUE");		return DECISION_CONTINUE;	}	if (sm->identity == NULL || sm->currentId == -1) {		wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known "			   "yet -> CONTINUE");		return DECISION_CONTINUE;	}	wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> "		   "FAILURE");	return DECISION_FAILURE;}static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method){	return method == EAP_TYPE_IDENTITY ? TRUE : FALSE;}/** * 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_set_eapRespData - Set EAP response (eapRespData) * @sm: Pointer to EAP state machine allocated with eap_sm_init() * @eapRespData: EAP-Response payload from the supplicant * @eapRespDataLen: Length of eapRespData in bytes * * This function is called when an EAP-Response is received from a supplicant. */void eap_set_eapRespData(struct eap_sm *sm, const u8 *eapRespData,			 size_t eapRespDataLen){	if (sm == NULL)		return;	free(sm->eapRespData);	sm->eapRespData = malloc(eapRespDataLen);	if (sm->eapRespData == NULL)		return;	memcpy(sm->eapRespData, eapRespData, eapRespDataLen);	sm->eapRespDataLen = eapRespDataLen;	wpa_hexdump(MSG_MSGDUMP, "EAP: EAP-Response received",		    eapRespData, eapRespDataLen);}static void eap_user_free(struct eap_user *user){	if (user == NULL)		return;	free(user->password);	user->password = NULL;	free(user);}/** * 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 * @conf: EAP configuration * Returns: Pointer to the allocated EAP state machine or %NULL on failure * * This function allocates and initializes an EAP state machine. */struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,			    struct eap_config *conf){	struct eap_sm *sm;	sm = wpa_zalloc(sizeof(*sm));	if (sm == NULL)		return NULL;	sm->eapol_ctx = eapol_ctx;	sm->eapol_cb = eapol_cb;	sm->MaxRetrans = 10;	sm->ssl_ctx = conf->ssl_ctx;	sm->eap_sim_db_priv = conf->eap_sim_db_priv;	sm->backend_auth = conf->backend_auth;	wpa_printf(MSG_DEBUG, "EAP: State machine created");	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;	wpa_printf(MSG_DEBUG, "EAP: State machine removed");	if (sm->m && sm->eap_method_priv)		sm->m->reset(sm, sm->eap_method_priv);	free(sm->eapReqData);	free(sm->eapKeyData);	free(sm->lastReqData);	free(sm->eapRespData);	free(sm->identity);	eap_user_free(sm->user);	free(sm);}/** * eap_sm_notify_cached - Notify EAP state machine of cached PMK * @sm: Pointer to EAP state machine allocated with eap_sm_init() * * This function is called when PMKSA caching is used to skip EAP * authentication. */void eap_sm_notify_cached(struct eap_sm *sm){	if (sm == NULL)		return;	sm->EAP_state = EAP_SUCCESS;}/** * eap_sm_pending_cb - EAP state machine callback for a pending EAP request * @sm: Pointer to EAP state machine allocated with eap_sm_init() * * This function is called when data for a pending EAP-Request is received. */void eap_sm_pending_cb(struct eap_sm *sm){	if (sm == NULL)		return;	wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received");	if (sm->method_pending == METHOD_PENDING_WAIT)		sm->method_pending = METHOD_PENDING_CONT;}/** * eap_sm_method_pending - Query whether EAP method is waiting for pending data * @sm: Pointer to EAP state machine allocated with eap_sm_init() * Returns: 1 if method is waiting for pending data or 0 if not */int eap_sm_method_pending(struct eap_sm *sm){	if (sm == NULL)		return 0;	return sm->method_pending == METHOD_PENDING_WAIT;}/** * eap_hdr_validate - Validate EAP header * @vendor: Expected EAP Vendor-Id (0 = IETF) * @eap_type: Expected EAP type number * @msg: EAP frame (starting with EAP header) * @msglen: Length of msg * @plen: Pointer to variable to contain the returned payload length * Returns: Pointer to EAP payload (after type field), or %NULL on failure * * This is a helper function for EAP method implementations. This is usually * called in the beginning of struct eap_method::process() function to verify * that the received EAP request packet has a valid header. This function is * able to process both legacy and expanded EAP headers and in most cases, the * caller can just use the returned payload pointer (into *plen) for processing * the payload regardless of whether the packet used the expanded EAP header or * not. */const u8 * eap_hdr_validate(int vendor, EapType eap_type,			    const u8 *msg, size_t msglen, size_t *plen){	const struct eap_hdr *hdr;	const u8 *pos;	size_t len;	hdr = (const struct eap_hdr *) msg;	if (msglen < sizeof(*hdr)) {		wpa_printf(MSG_INFO, "EAP: Too short EAP frame");		return NULL;	}	len = be_to_host16(hdr->length);	if (len < sizeof(*hdr) + 1 || len > msglen) {		wpa_printf(MSG_INFO, "EAP: Invalid EAP length");		return NULL;	}	pos = (const u8 *) (hdr + 1);	if (*pos == EAP_TYPE_EXPANDED) {		int exp_vendor;		u32 exp_type;		if (len < sizeof(*hdr) + 8) {			wpa_printf(MSG_INFO, "EAP: Invalid expanded EAP "				   "length");			return NULL;		}		pos++;		exp_vendor = WPA_GET_BE24(pos);		pos += 3;		exp_type = WPA_GET_BE32(pos);		pos += 4;		if (exp_vendor != vendor || exp_type != (u32) eap_type) {			wpa_printf(MSG_INFO, "EAP: Invalid expanded frame "				   "type");			return NULL;		}		*plen = len - sizeof(*hdr) - 8;		return pos;	} else {		if (vendor != EAP_VENDOR_IETF || *pos != eap_type) {			wpa_printf(MSG_INFO, "EAP: Invalid frame type");			return NULL;		}		*plen = len - sizeof(*hdr) - 1;		return pos + 1;	}}/** * eap_msg_alloc - Allocate a buffer for an EAP message * @vendor: Vendor-Id (0 = IETF) * @type: EAP type * @len: Buffer for returning message length * @payload_len: Payload length in bytes (data after Type) * @code: Message Code (EAP_CODE_*) * @identifier: Identifier * @payload: Pointer to payload pointer that will be set to point to the * beginning of the payload or %NULL if payload pointer is not needed * Returns: Pointer to the allocated message buffer or %NULL on error * * This function can be used to allocate a buffer for an EAP message and fill * in the EAP header. This function is automatically using expanded EAP header * if the selected Vendor-Id is not IETF. In other words, most EAP methods do * not need to separately select which header type to use when using this * function to allocate the message buffers. */struct eap_hdr * eap_msg_alloc(int vendor, EapType type, size_t *len,			       size_t payload_len, u8 code, u8 identifier,			       u8 **payload){	struct eap_hdr *hdr;	u8 *pos;	*len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) +		payload_len;	hdr = malloc(*len);	if (hdr) {		hdr->code = code;		hdr->identifier = identifier;		hdr->length = host_to_be16(*len);		pos = (u8 *) (hdr + 1);		if (vendor == EAP_VENDOR_IETF) {			*pos++ = type;		} else {			*pos++ = EAP_TYPE_EXPANDED;			WPA_PUT_BE24(pos, vendor);			pos += 3;			WPA_PUT_BE32(pos, type);			pos += 4;		}		if (payload)			*payload = pos;	}	return hdr;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -