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

📄 ieee802_1x.c

📁 802.1x 源码,基于linux平台开发
💻 C
📖 第 1 页 / 共 2 页
字号:
	data++;
	len--;

	/* TODO: IEEE 802.1aa/D4: should use auth_pae.initialEAPMsg to check
	 * which EAP packet is accepted as response; currently, hostapd only
	 * supports EAP Response-Identity, so this can be hardcoded */
	if (type == EAP_TYPE_IDENTITY)
	{
		char *buf, *pos;
		int i;

		buf = malloc(4 * len + 1);
		if (buf)
		{
			pos = buf;
			for (i = 0; i < len; i++)
			{
				if (data[i] >= 32 && data[i] < 127)
					*pos++ = data[i];
				else
				{
					snprintf(pos, 5, "{%02x}", data[i]);
					pos += 4;
				}
			}
			*pos = '\0';
			free(buf);
		}

		sta->eapol_sm->auth_pae.rxInitialRsp = TRUE;

		/* Save station identity for future RADIUS packets */
		if (sta->identity)
			free(sta->identity);
		sta->identity = (u8 *) malloc(len);
		if (sta->identity)
		{
			memcpy(sta->identity, data, len);
			sta->identity_len = len;
		}
	}
	else
	{
		if (type != EAP_TYPE_NAK)
			sta->eapol_sm->be_auth.backendNonNakResponsesFromSupplicant++;
		sta->eapol_sm->be_auth.rxResp = TRUE;
	}
}

/* Process incoming EAP packet from Supplicant */
static void handle_eap(struct sta_info *sta, u8 *buf, size_t len)
{
	struct eap_hdr *eap;
	u16 eap_len;
//fprintf(stderr, "      handle_eap\n");

	if (len < sizeof(*eap))
	{
		DBGPRINT(RT_DEBUG_ERROR," too short EAP packet\n");
		return;
	}

	eap = (struct eap_hdr *) buf;

	eap_len = ntohs(eap->length);
	DBGPRINT(RT_DEBUG_INFO," Receive EAP: code=%d identifier=%d length=%d from Supplicant ra%d\n",
			  eap->code, eap->identifier, eap_len,sta->ApIdx);
	if (eap_len < sizeof(*eap))
	{
		DBGPRINT(RT_DEBUG_ERROR,"Invalid EAP length\n");
		return;
	}
	else if (eap_len > len)
	{
		DBGPRINT(RT_DEBUG_ERROR,"Too short frame to contain this EAP packet\n");
		return;
	}
	else if (eap_len < len)
	{
		DBGPRINT(RT_DEBUG_WARN,"Ignoring %d extra bytes after EAP packet\n", len - eap_len);
	}

	eap_len -= LENGTH_8021X_HDR;

	switch (eap->code)
	{
		case EAP_CODE_REQUEST:
			return;

		case EAP_CODE_RESPONSE:
			handle_eap_response( sta, eap, (u8 *) (eap + 1), eap_len);
			break;

		case EAP_CODE_SUCCESS:
			return;

		case EAP_CODE_FAILURE:
			return;

		default:
			return;
	}
}

/* called from Recv_Eapol(). Process the EAPOL frames from the Supplicant */
void ieee802_1x_receive(rtapd *rtapd, u8 *sa, u8 *apidx, u8 *buf, size_t len, u16 ethertype)
{
	struct sta_info *sta;
	struct ieee802_1x_hdr *hdr;
	char SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
	char RalinkDiscardIe[] = {0x01, 0xFE, 0x00, 0x06, 0x52, 0x61, 0x6c, 0x69, 0x6e, 0x6b};
	u16 datalen;
	int bStop = 0;
	int i;
//fprintf(stderr, "     ieee802_1x_receive\n");

	DBGPRINT(RT_DEBUG_INFO,"IEEE802_1X_RECEIVE : from Supplicant\n");
	if (len == 10 && RTMPCompareMemory(buf, RalinkDiscardIe, 10) == 0)
		bStop = 1;
	
	sta = Ap_get_sta(rtapd, sa, apidx, ethertype, bStop);
	if (!sta)
	{
		return;
	}
	if (RTMPCompareMemory(buf, SNAP_802_1H, 6) == 0)
		buf += LENGTH_802_1_H;
	hdr = (struct ieee802_1x_hdr *) buf;
	datalen = ntohs(hdr->length);
	if (len - sizeof(*hdr) < datalen)
	{
		DBGPRINT(RT_DEBUG_ERROR,"Frame too short for this IEEE 802.1X packet\n");
		return;
	}

	if (!sta->eapol_sm)
	{
		sta->eapol_sm = eapol_sm_alloc(rtapd, sta);
		if (!sta->eapol_sm)
			return;
	}

	if (((ethertype == ETH_P_PAE) && (hdr->version != EAPOL_VERSION)) || ((ethertype == ETH_P_PRE_AUTH) && (hdr->version != EAPOL_VERSION_2)))
	{
		DBGPRINT(RT_DEBUG_ERROR,"Key descripter does not match with WPA rule\n");
		return;
	}

	switch (hdr->type)
	{
		case IEEE802_1X_TYPE_EAP_PACKET:
			DBGPRINT(RT_DEBUG_TRACE,"Handle EAP_PACKET from ixp%d\n",sta->ApIdx);
			handle_eap(sta, (buf + LENGTH_8021X_HDR), datalen);
			break;

		case IEEE802_1X_TYPE_EAPOL_START:
			DBGPRINT(RT_DEBUG_TRACE,"Handle EAPOL_START from ixp%d\n",sta->ApIdx);
                    //eapol_sm_initialize(sta->eapol_sm);/*add by caoyue*/
                    eapol_sm_reinit_port_timer(sta->eapol_sm);
			sta->eapol_sm->auth_pae.eapStart = TRUE;
                    DBGPRINT(RT_DEBUG_TRACE,"  ieee802_1x_receive IEEE802_1X_TYPE_EAPOL_START call eapol_sm_step\n");
			eapol_sm_step(sta->eapol_sm);
			break;

		case IEEE802_1X_TYPE_EAPOL_LOGOFF:
			sta->eapol_sm->auth_pae.eapLogoff = TRUE;
            DBGPRINT(RT_DEBUG_TRACE,"  ieee802_1x_receive IEEE802_1X_TYPE_EAPOL_START call eapol_sm_step\n");    
			eapol_sm_step(sta->eapol_sm);            
			break;

		case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
			/* TODO: */
			DBGPRINT(RT_DEBUG_TRACE,"Handle EAPOL_ALERT from ra%d\n",sta->ApIdx);
			break;

		default:
			DBGPRINT(RT_DEBUG_TRACE,"Handle Unknown EAP message(Type:%d) from ra%d\n",hdr->type,sta->ApIdx);
			break;
	}

        DBGPRINT(RT_DEBUG_TRACE,"  ieee802_1x_receive call eapol_sm_step\n");    
//fprintf(stderr, "     ieee802_1x_receive call eapol_sm_step\n");        
	eapol_sm_step(sta->eapol_sm);
//fprintf(stderr, "     ieee802_1x_receive call eapol_sm_step over\n");        
}

void ieee802_1x_new_station(rtapd *rtapd, struct sta_info *sta)
{
	if (sta->eapol_sm)
	{
		sta->eapol_sm->portEnabled = TRUE;
        DBGPRINT(RT_DEBUG_TRACE,"  ieee802_1x_new_station call eapol_sm_step\n");    
		eapol_sm_step(sta->eapol_sm);
		return;
	}

	sta->eapol_sm = eapol_sm_alloc(rtapd, sta);
	if (sta->eapol_sm)
		sta->eapol_sm->portEnabled = TRUE;
}

void ieee802_1x_free_station(struct sta_info *sta)
{
	if (sta->last_recv_radius)
	{
		Radius_msg_free(sta->last_recv_radius);
		free(sta->last_recv_radius);
		sta->last_recv_radius = NULL;
	}

	free(sta->last_eap_supp);
	sta->last_eap_supp = NULL;

	free(sta->last_eap_radius);
	sta->last_eap_radius = NULL;

	free(sta->identity);
	sta->identity = NULL;

	free(sta->eapol_key_sign);
	sta->eapol_key_sign = NULL;

	free(sta->eapol_key_crypt);
	sta->eapol_key_crypt = NULL;

	eapol_sm_free(sta->eapol_sm);
	sta->eapol_sm = NULL;
}

static void ieee802_1x_decapsulate_radius(struct sta_info *sta)
{
	char *eap;
	size_t len;
	struct eap_hdr *hdr;
	int eap_type = -1;
	struct radius_msg *msg;

	if (sta->last_recv_radius == NULL)
		return;

	msg = sta->last_recv_radius;
	eap = Radius_msg_get_eap(msg, &len);
	if (eap == NULL)
	{
		/* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3:
		 * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
		 * attribute */
		free(sta->last_eap_radius);
		sta->last_eap_radius = NULL;
		sta->last_eap_radius_len = 0;
		return;
	}

	if (len < sizeof(*hdr))
	{
		free(eap);
		return;
	}

	if (len > sizeof(*hdr))
		eap_type = eap[sizeof(*hdr)];

	hdr = (struct eap_hdr *) eap;

	sta->eapol_sm->be_auth.idFromServer = hdr->identifier;

	if (sta->last_eap_radius)
		free(sta->last_eap_radius);
	sta->last_eap_radius = eap;
	sta->last_eap_radius_len = len;
}

#if 0	
static void ieee802_1x_get_keys(rtapd *rtapd, struct sta_info *sta,
				struct radius_msg *msg, struct radius_msg *req,
				u8 *shared_secret, size_t shared_secret_len)
{
	struct radius_ms_mppe_keys *keys;
	NDIS_802_11_KEY 	WepKey;
	memset(&WepKey, 0,sizeof(NDIS_802_11_KEY));
	keys = Radius_msg_get_ms_keys(msg, req, shared_secret, shared_secret_len);
	
	if(keys && keys->recv_len != 0)
	{
	DBGPRINT(RT_DEBUG_INFO, "IEEE802_1x_Get_Keys, PMK_len = %d\n",keys->recv_len );
	DBGPRINT(RT_DEBUG_TRACE, "PMK = %x %x %x %x %x %x %x ...%x \n",\
		keys->recv[0],keys->recv[1],keys->recv[2],keys->recv[3],\
		keys->recv[4],keys->recv[5],keys->recv[6],keys->recv[15]);
	DBGPRINT(RT_DEBUG_INFO, "PMK[16] = %x %x %x %x %x %x %x %x \n",\
		keys->recv[16],keys->recv[17],keys->recv[18],keys->recv[19],\
		keys->recv[20],keys->recv[21],keys->recv[22],keys->recv[23]);

	WepKey.KeyLength = keys->recv_len;
	memcpy(WepKey.KeyMaterial, keys->recv, (keys->recv_len== 32?32:1));
	memcpy(WepKey.addr, sta->addr, 6);

	// WPA2(pre-auth)
	if (sta->ethertype == ETH_P_PRE_AUTH)
	{
		if (RT_ioctl(rtapd, RTPRIV_IOCTL_ADD_PMKID_CACHE, (u8*)&WepKey, sizeof(NDIS_802_11_KEY), 0))
		{
			DBGPRINT(RT_DEBUG_ERROR,"ieee802_1x_get_keys:RTPRIV_IOCTL_ADD_PMKID_CACHE\n");
			return;
		}
	}
	else
	{
		if (RT_ioctl(rtapd, RTPRIV_IOCTL_ADD_WPA_KEY, (u8*)&WepKey, sizeof(NDIS_802_11_KEY), sta->ApIdx))
		{
			DBGPRINT(RT_DEBUG_ERROR,"ieee802_1x_get_keys:RTPRIV_IOCTL_ADD_WPA_KEY\n");
			return;
		}
	}

	
		if (keys->send && keys->recv)
		{
			free(sta->eapol_key_sign);
			free(sta->eapol_key_crypt);
			sta->eapol_key_sign = keys->send;
			sta->eapol_key_sign_len = keys->send_len;
			sta->eapol_key_crypt = keys->recv;
			sta->eapol_key_crypt_len = keys->recv_len;
				sta->eapol_sm->keyAvailable = TRUE;
		}
		else
		{
			free(keys->send);
			free(keys->recv);
		}
		free(keys);
	}
}
#endif

/* Process the RADIUS frames from Authentication Server */
static RadiusRxResult
ieee802_1x_receive_auth(rtapd *rtapd, struct radius_msg *msg, struct radius_msg *req,
			u8 *shared_secret, size_t shared_secret_len, void *data)
{
	struct sta_info *sta;
	u32 session_timeout = 88, termination_action;
	int session_timeout_set, free_flag = 0;

	DBGPRINT(RT_DEBUG_TRACE,"Receive IEEE802_1X Response Packet From Radius Server. \n");

	sta = Ap_get_sta_radius_identifier(rtapd, msg->hdr->identifier);
//fprintf(stderr, "Radius Rcv  id=%d ,sta=%d\n",msg->hdr->identifier,sta);
    
	if (sta == NULL)
	{
		return RADIUS_RX_UNKNOWN;
	}

	/* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
	 * present when packet contains an EAP-Message attribute */
	if (msg->hdr->code == RADIUS_CODE_ACCESS_REJECT && Radius_msg_get_attr(msg,
		RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL, 0) < 0 &&
		Radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0)
	{
	}
	else if (Radius_msg_verify(msg, shared_secret, shared_secret_len, req))
	{
		DBGPRINT(RT_DEBUG_ERROR,"Incoming RADIUS packet did not have correct Message-Authenticator - dropped\n");
		return RADIUS_RX_UNKNOWN;
	}

	if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
		msg->hdr->code != RADIUS_CODE_ACCESS_REJECT &&
		msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE)
	{
		DBGPRINT(RT_DEBUG_WARN,"Unknown RADIUS message code\n");
		return RADIUS_RX_UNKNOWN;
	}

	sta->radius_identifier = -1;

	if (sta->last_recv_radius)
	{
		Radius_msg_free(sta->last_recv_radius);
		free(sta->last_recv_radius);
	}

	sta->last_recv_radius = msg;

	session_timeout_set = !Radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, &session_timeout);
	if (Radius_msg_get_attr_int32(msg, RADIUS_ATTR_TERMINATION_ACTION, &termination_action))
		termination_action = RADIUS_TERMINATION_ACTION_DEFAULT;

	switch (msg->hdr->code)
	{
		case RADIUS_CODE_ACCESS_ACCEPT:
			/* draft-congdon-radius-8021x-22.txt, Ch. 3.17 */
			if (session_timeout_set && termination_action == RADIUS_TERMINATION_ACTION_RADIUS_REQUEST)
			{
				sta->eapol_sm->reauth_timer.reAuthPeriod =	session_timeout;
			}
			else if (session_timeout_set && (rtapd->conf->session_timeout_set == 1))   // 1 1 
			{
				Ap_sta_session_timeout(rtapd, sta, ((session_timeout<rtapd->conf->session_timeout_interval) ? session_timeout : rtapd->conf->session_timeout_interval));
			}
			else if (session_timeout_set )   // 1 0 
			{
				Ap_sta_session_timeout(rtapd, sta, session_timeout);
			}
			else if (rtapd->conf->session_timeout_set == 1)   // 0 1
			{
				Ap_sta_session_timeout(rtapd, sta, rtapd->conf->session_timeout_interval);
			}
			else  // 0 0
				free_flag = 1;
			sta->eapol_sm->be_auth.aSuccess = TRUE;
//			ieee802_1x_get_keys(rtapd, sta, msg, req, shared_secret, shared_secret_len);
			break;

		case RADIUS_CODE_ACCESS_REJECT:
			DBGPRINT(RT_DEBUG_ERROR,"AS send RADIUS_CODE_ACCESS_REJECT\n");
			sta->eapol_sm->be_auth.aFail = TRUE;
			break;

		case RADIUS_CODE_ACCESS_CHALLENGE:
			if (session_timeout_set)
			{
				/* RFC 2869, Ch. 2.3.2
				 * draft-congdon-radius-8021x-22.txt, Ch. 3.17 */
				sta->eapol_sm->be_auth.suppTimeout = session_timeout;
			}
			sta->eapol_sm->be_auth.aReq = TRUE;
			break;
	}

	ieee802_1x_decapsulate_radius(sta);
    DBGPRINT(RT_DEBUG_TRACE,"  ieee802_1x_receive_auth call eapol_sm_step\n");    
	eapol_sm_step(sta->eapol_sm);


	if (free_flag == 1)
		Ap_free_sta(rtapd, sta);
	return RADIUS_RX_QUEUED;
}


/* Handler for EAPOL Backend Authentication state machine sendRespToServer.
 * Forward the EAP Response from Supplicant to Authentication Server. */
void ieee802_1x_send_resp_to_server(rtapd *rtapd, struct sta_info *sta)
{
	ieee802_1x_encapsulate_radius(rtapd, sta, sta->last_eap_supp, sta->last_eap_supp_len);
}

int ieee802_1x_init(rtapd *rtapd)
{
	if (Radius_client_register(rtapd, RADIUS_AUTH, ieee802_1x_receive_auth, NULL))
		return -1;

	return 0;
}

void ieee802_1x_new_auth_session(rtapd *rtapd, struct sta_info *sta)
{
	if (!sta->last_recv_radius)
		return;

	Radius_msg_free(sta->last_recv_radius);
	free(sta->last_recv_radius);
	sta->last_recv_radius = NULL;
}

⌨️ 快捷键说明

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