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

📄 eapol_supp_sm.c

📁 IEEE 802.11a/b/g 服务器端AP
💻 C
📖 第 1 页 / 共 4 页
字号:
		break;	}}SM_STATE(SUPP_BE, REQUEST){	SM_ENTRY(SUPP_BE, REQUEST);	sm->authWhile = 0;	sm->eapReq = TRUE;	eapol_sm_getSuppRsp(sm);}SM_STATE(SUPP_BE, RESPONSE){	SM_ENTRY(SUPP_BE, RESPONSE);	eapol_sm_txSuppRsp(sm);	sm->eapResp = FALSE;}SM_STATE(SUPP_BE, SUCCESS){	SM_ENTRY(SUPP_BE, SUCCESS);	sm->keyRun = TRUE;	sm->suppSuccess = TRUE;	if (eap_key_available(sm->eap)) {		/* New key received - clear IEEE 802.1X EAPOL-Key replay		 * counter */		sm->replay_counter_valid = FALSE;	}}SM_STATE(SUPP_BE, FAIL){	SM_ENTRY(SUPP_BE, FAIL);	sm->suppFail = TRUE;}SM_STATE(SUPP_BE, TIMEOUT){	SM_ENTRY(SUPP_BE, TIMEOUT);	sm->suppTimeout = TRUE;}SM_STATE(SUPP_BE, IDLE){	SM_ENTRY(SUPP_BE, IDLE);	sm->suppStart = FALSE;	sm->initial_req = TRUE;}SM_STATE(SUPP_BE, INITIALIZE){	SM_ENTRY(SUPP_BE, INITIALIZE);	eapol_sm_abortSupp(sm);	sm->suppAbort = FALSE;}SM_STATE(SUPP_BE, RECEIVE){	SM_ENTRY(SUPP_BE, RECEIVE);	sm->authWhile = sm->authPeriod;	eapol_enable_timer_tick(sm);	sm->eapolEap = FALSE;	sm->eapNoResp = FALSE;	sm->initial_req = FALSE;}SM_STEP(SUPP_BE){	if (sm->initialize || sm->suppAbort)		SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);	else switch (sm->SUPP_BE_state) {	case SUPP_BE_UNKNOWN:		break;	case SUPP_BE_REQUEST:		/*		 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL		 * and SUCCESS based on eapFail and eapSuccess, respectively.		 * However, IEEE Std 802.1X-2004 is also specifying that		 * eapNoResp should be set in conjuction with eapSuccess and		 * eapFail which would mean that more than one of the		 * transitions here would be activated at the same time.		 * Skipping RESPONSE and/or RECEIVE states in these cases can		 * cause problems and the direct transitions to do not seem		 * correct. Because of this, the conditions for these		 * transitions are verified only after eapNoResp. They are		 * unlikely to be used since eapNoResp should always be set if		 * either of eapSuccess or eapFail is set.		 */		if (sm->eapResp && sm->eapNoResp) {			wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "				   "eapResp and eapNoResp set?!");		}		if (sm->eapResp)			SM_ENTER(SUPP_BE, RESPONSE);		else if (sm->eapNoResp)			SM_ENTER(SUPP_BE, RECEIVE);		else if (sm->eapFail)			SM_ENTER(SUPP_BE, FAIL);		else if (sm->eapSuccess)			SM_ENTER(SUPP_BE, SUCCESS);		break;	case SUPP_BE_RESPONSE:		SM_ENTER(SUPP_BE, RECEIVE);		break;	case SUPP_BE_SUCCESS:		SM_ENTER(SUPP_BE, IDLE);		break;	case SUPP_BE_FAIL:		SM_ENTER(SUPP_BE, IDLE);		break;	case SUPP_BE_TIMEOUT:		SM_ENTER(SUPP_BE, IDLE);		break;	case SUPP_BE_IDLE:		if (sm->eapFail && sm->suppStart)			SM_ENTER(SUPP_BE, FAIL);		else if (sm->eapolEap && sm->suppStart)			SM_ENTER(SUPP_BE, REQUEST);		else if (sm->eapSuccess && sm->suppStart)			SM_ENTER(SUPP_BE, SUCCESS);		break;	case SUPP_BE_INITIALIZE:		SM_ENTER(SUPP_BE, IDLE);		break;	case SUPP_BE_RECEIVE:		if (sm->eapolEap)			SM_ENTER(SUPP_BE, REQUEST);		else if (sm->eapFail)			SM_ENTER(SUPP_BE, FAIL);		else if (sm->authWhile == 0)			SM_ENTER(SUPP_BE, TIMEOUT);		else if (sm->eapSuccess)			SM_ENTER(SUPP_BE, SUCCESS);		break;	}}static void eapol_sm_txLogoff(struct eapol_sm *sm){	wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");	sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,			    IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);	sm->dot1xSuppEapolLogoffFramesTx++;	sm->dot1xSuppEapolFramesTx++;}static void eapol_sm_txStart(struct eapol_sm *sm){	wpa_printf(MSG_DEBUG, "EAPOL: txStart");	sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,			    IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);	sm->dot1xSuppEapolStartFramesTx++;	sm->dot1xSuppEapolFramesTx++;}#define IEEE8021X_ENCR_KEY_LEN 32#define IEEE8021X_SIGN_KEY_LEN 32struct eap_key_data {	u8 encr_key[IEEE8021X_ENCR_KEY_LEN];	u8 sign_key[IEEE8021X_SIGN_KEY_LEN];};static void eapol_sm_processKey(struct eapol_sm *sm){	struct ieee802_1x_hdr *hdr;	struct ieee802_1x_eapol_key *key;	struct eap_key_data keydata;	u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];	u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];	int key_len, res, sign_key_len, encr_key_len;	u16 rx_key_length;	wpa_printf(MSG_DEBUG, "EAPOL: processKey");	if (sm->last_rx_key == NULL)		return;	if (!sm->conf.accept_802_1x_keys) {		wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"			   " even though this was not accepted - "			   "ignoring this packet");		return;	}	hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;	key = (struct ieee802_1x_eapol_key *) (hdr + 1);	if (sizeof(*hdr) + be_to_host16(hdr->length) > sm->last_rx_key_len) {		wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");		return;	}	rx_key_length = WPA_GET_BE16(key->key_length);	wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "		   "EAPOL-Key: type=%d key_length=%d key_index=0x%x",		   hdr->version, hdr->type, be_to_host16(hdr->length),		   key->type, rx_key_length, key->key_index);	eapol_sm_notify_lower_layer_success(sm, 1);	sign_key_len = IEEE8021X_SIGN_KEY_LEN;	encr_key_len = IEEE8021X_ENCR_KEY_LEN;	res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));	if (res < 0) {		wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "			   "decrypting EAPOL-Key keys");		return;	}	if (res == 16) {		/* LEAP derives only 16 bytes of keying material. */		res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);		if (res) {			wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "				   "master key for decrypting EAPOL-Key keys");			return;		}		sign_key_len = 16;		encr_key_len = 16;		os_memcpy(keydata.sign_key, keydata.encr_key, 16);	} else if (res) {		wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "			   "data for decrypting EAPOL-Key keys (res=%d)", res);		return;	}	/* The key replay_counter must increase when same master key */	if (sm->replay_counter_valid &&	    os_memcmp(sm->last_replay_counter, key->replay_counter,		      IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {		wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "			   "not increase - ignoring key");		wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",			    sm->last_replay_counter,			    IEEE8021X_REPLAY_COUNTER_LEN);		wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",			    key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);		return;	}	/* Verify key signature (HMAC-MD5) */	os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);	os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);	hmac_md5(keydata.sign_key, sign_key_len,		 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),		 key->key_signature);	if (os_memcmp(orig_key_sign, key->key_signature,		      IEEE8021X_KEY_SIGN_LEN) != 0) {		wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "			   "EAPOL-Key packet");		os_memcpy(key->key_signature, orig_key_sign,			  IEEE8021X_KEY_SIGN_LEN);		return;	}	wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");	key_len = be_to_host16(hdr->length) - sizeof(*key);	if (key_len > 32 || rx_key_length > 32) {		wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",			   key_len ? key_len : rx_key_length);		return;	}	if (key_len == rx_key_length) {		os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);		os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,			  encr_key_len);		os_memcpy(datakey, key + 1, key_len);		rc4(datakey, key_len, ekey,		    IEEE8021X_KEY_IV_LEN + encr_key_len);		wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",				datakey, key_len);	} else if (key_len == 0) {		/*		 * IEEE 802.1X-2004 specifies that least significant Key Length		 * octets from MS-MPPE-Send-Key are used as the key if the key		 * data is not present. This seems to be meaning the beginning		 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in		 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.		 * Anyway, taking the beginning of the keying material from EAP		 * seems to interoperate with Authenticators.		 */		key_len = rx_key_length;		os_memcpy(datakey, keydata.encr_key, key_len);		wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "				"material data encryption key",				datakey, key_len);	} else {		wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "			   "(key_length=%d)", key_len, rx_key_length);		return;	}	sm->replay_counter_valid = TRUE;	os_memcpy(sm->last_replay_counter, key->replay_counter,		  IEEE8021X_REPLAY_COUNTER_LEN);	wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "		   "len %d",		   key->key_index & IEEE8021X_KEY_INDEX_FLAG ?		   "unicast" : "broadcast",		   key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);	if (sm->ctx->set_wep_key &&	    sm->ctx->set_wep_key(sm->ctx->ctx,				 key->key_index & IEEE8021X_KEY_INDEX_FLAG,				 key->key_index & IEEE8021X_KEY_INDEX_MASK,				 datakey, key_len) < 0) {		wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "			   " driver.");	} else {		if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)			sm->unicast_key_received = TRUE;		else			sm->broadcast_key_received = TRUE;		if ((sm->unicast_key_received ||		     !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&		    (sm->broadcast_key_received ||		     !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))		{			wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "				   "frames received");			sm->portValid = TRUE;			if (sm->ctx->eapol_done_cb)				sm->ctx->eapol_done_cb(sm->ctx->ctx);		}	}}static void eapol_sm_getSuppRsp(struct eapol_sm *sm){	wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");	/* EAP layer processing; no special code is needed, since Supplicant	 * Backend state machine is waiting for eapNoResp or eapResp to be set	 * and these are only set in the EAP state machine when the processing	 * has finished. */}static void eapol_sm_txSuppRsp(struct eapol_sm *sm){	struct wpabuf *resp;	wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");	resp = eap_get_eapRespData(sm->eap);	if (resp == NULL) {		wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "			   "not available");		return;	}	/* Send EAP-Packet from the EAP layer to the Authenticator */	sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,			    IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),			    wpabuf_len(resp));	/* eapRespData is not used anymore, so free it here */	wpabuf_free(resp);	if (sm->initial_req)		sm->dot1xSuppEapolReqIdFramesRx++;	else		sm->dot1xSuppEapolReqFramesRx++;	sm->dot1xSuppEapolRespFramesTx++;	sm->dot1xSuppEapolFramesTx++;}static void eapol_sm_abortSupp(struct eapol_sm *sm){	/* release system resources that may have been allocated for the	 * authentication session */	os_free(sm->last_rx_key);	sm->last_rx_key = NULL;	wpabuf_free(sm->eapReqData);	sm->eapReqData = NULL;	eap_sm_abort(sm->eap);}static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx){	eapol_sm_step(timeout_ctx);}/** * eapol_sm_step - EAPOL state machine step function * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * * This function is called to notify the state machine about changed external * variables. It will step through the EAPOL state machines in loop to process * all triggered state changes. */void eapol_sm_step(struct eapol_sm *sm){	int i;	/* In theory, it should be ok to run this in loop until !changed.	 * However, it is better to use a limit on number of iterations to	 * allow events (e.g., SIGTERM) to stop the program cleanly if the	 * state machine were to generate a busy loop. */	for (i = 0; i < 100; i++) {		sm->changed = FALSE;		SM_STEP_RUN(SUPP_PAE);		SM_STEP_RUN(KEY_RX);		SM_STEP_RUN(SUPP_BE);		if (eap_peer_sm_step(sm->eap))			sm->changed = TRUE;		if (!sm->changed)			break;	}	if (sm->changed) {		/* restart EAPOL state machine step from timeout call in order		 * to allow other events to be processed. */		eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);		eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);	}	if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {		int success = sm->cb_status == EAPOL_CB_SUCCESS ? 1 : 0;		sm->cb_status = EAPOL_CB_IN_PROGRESS;		sm->ctx->cb(sm, success, sm->ctx->cb_ctx);	}}#ifdef CONFIG_CTRL_IFACEstatic const char *eapol_supp_pae_state(int state){	switch (state) {	case SUPP_PAE_LOGOFF:		return "LOGOFF";	case SUPP_PAE_DISCONNECTED:		return "DISCONNECTED";	case SUPP_PAE_CONNECTING:		return "CONNECTING";	case SUPP_PAE_AUTHENTICATING:		return "AUTHENTICATING";	case SUPP_PAE_HELD:		return "HELD";	case SUPP_PAE_AUTHENTICATED:		return "AUTHENTICATED";	case SUPP_PAE_RESTART:		return "RESTART";	default:		return "UNKNOWN";	}

⌨️ 快捷键说明

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