wpa.c
来自「Ralink RT61 SoftAP Driver source code. 」· C语言 代码 · 共 1,629 行 · 第 1/5 页
C
1,629 行
return TRUE;
}
}
else
{// single cipher
if (RTMPEqualMemory(&eid_ptr->Octet[8], &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[IE_Idx][8], 4))
return TRUE;
}
}
}
DBGPRINT(RT_DEBUG_ERROR, "RTMPCheckUcast ==> WPAIE parsing error, WPAIE=%d\n", eid_ptr->Eid);
return FALSE;
}
/*
==========================================================================
Description:
Check invalidity of authentication method selection in RSN IE.
Return:
TRUE if match
FALSE otherwise
==========================================================================
*/
BOOLEAN RTMPCheckAKM(PUCHAR sta_akm, PUCHAR ap_rsn_ie, INT iswpa2)
{
PUCHAR pTmp;
USHORT Count;
//pTmp = &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[0][0];
//rtmp_hexdump(RT_DEBUG_TRACE,"MBSS WPA_IE ",ap_rsn_ie,24);
//rtmp_hexdump(RT_DEBUG_TRACE,"MBSS STA AKM ",sta_akm,4);
pTmp = ap_rsn_ie;
if(iswpa2)
// skip Version(2),Multicast cipter(4) 2+4==6
pTmp +=6;
else
//skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10
pTmp += 10;//point to number of unicast
NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
#ifdef BIG_ENDIAN
Count = SWAP16(Count);
#endif
pTmp += sizeof(USHORT);//pointer to unicast cipher
// Skip all unicast cipher suite
while (Count > 0)
{
// Skip OUI
pTmp += 4;
Count--;
}
NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
#ifdef BIG_ENDIAN
Count = SWAP16(Count);
#endif
pTmp += sizeof(USHORT);//pointer to AKM cipher
while (Count > 0)
{
//rtmp_hexdump(RT_DEBUG_TRACE,"MBSS WPA_IE AKM ",pTmp,4);
if(RTMPEqualMemory(sta_akm,pTmp,4))
return TRUE;
else
{
pTmp += 4;
Count--;
}
}
return FALSE;// do not match the AKM
}
/*
==========================================================================
Description:
Check invalidity of authentication method selection in RSN IE.
Return:
TRUE if match
FALSE otherwise
==========================================================================
*/
BOOLEAN RTMPCheckAUTH(
IN PRTMP_ADAPTER pAdapter,
IN PEID_STRUCT eid_ptr,
IN MAC_TABLE_ENTRY *pEntry)
{
if (eid_ptr->Len >= 16)
{
if (eid_ptr->Eid == IE_WPA)
return RTMPCheckAKM(&eid_ptr->Octet[18],&pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[0][0],0);
else if (eid_ptr->Eid == IE_WPA2)
{
UCHAR IE_Idx = 0;
// When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure
if ((pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPAPSKWPA2PSK))
IE_Idx = 1;
return RTMPCheckAKM(&eid_ptr->Octet[14],&pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[IE_Idx][0],1);
}
}
DBGPRINT(RT_DEBUG_ERROR, "RTMPCheckAUTH ==> WPAIE parsing error, WPAIE=%d\n", eid_ptr->Eid);
return FALSE;
}
/*
==========================================================================
Description:
this is state machine function.
When receiving EAP packets which is for 802.1x authentication use.
Not use in PSK case
Return:
==========================================================================
*/
VOID WpaEAPPacketAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
}
VOID WpaEAPOLLogoffAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
}
VOID WpaEAPOLASFAlertAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
}
VOID WpaEAPOLStartAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
MAC_TABLE_ENTRY *pEntry;
PHEADER_802_11 pHeader;
DBGPRINT(RT_DEBUG_TRACE, "WpaEAPOLStartAction ====>> \n");
// Delay for avoiding the misorder of EAPOL-KEY and Assoc Rsp.
RTMPusecDelay(300000);
pHeader = (PHEADER_802_11)Elem->Msg;
// TODO: For normaol PSK, we enqueue an EAPOL-Start command to trigger the process.
if (Elem->MsgLen == 6)
pEntry = MacTableLookup(pAd, Elem->Msg);
else
pEntry = MacTableLookup(pAd, pHeader->Addr2);
if (pEntry)
{
// TODO: If WPA-PSK mode and port not secured, reset to the init PSK state
if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)
&& ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND))))
{
pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
pEntry->WpaState = AS_INITPSK;
pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
// add timer for retry
pEntry->RetryTimer.expires = jiffies + WPA_RETRY_EXEC_INTV;
pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
WPAStart4WayHS(pAd, pEntry);
}
}
}
/*
==========================================================================
Description:
Function to handel countermeasures active attack. Init 60-sec timer if necessary.
Return:
==========================================================================
*/
VOID HandleCounterMeasure(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pEntry)
{
INT i;
do{
if (!pEntry)
break;
// if entry not set key done, ignore this RX MIC ERROR
if ((pEntry->WpaState < AS_PTKINITDONE) || (pEntry->GTKState != REKEY_ESTABLISHED))
break;
DBGPRINT(RT_DEBUG_TRACE, "HandleCounterMeasure ===> \n");
pAd->PortCfg.MICFailureCounter++;
// record which entry causes this MIC error, if this entry sends disauth/disassoc, AP doesn't need to log the CM
pEntry->CMTimerRunning = TRUE;
if (pAd->PortCfg.CMTimerRunning == TRUE)
{
DBGPRINT(RT_DEBUG_TRACE, "Receive CM Attack Twice Within 60 seconds ====>>> \n");
ApLogEvent(pAd, pEntry->Addr, EVENT_COUNTER_M, pEntry->ApIdx);
RTMPCancelTimer(&pAd->PortCfg.CounterMeasureTimer);
pAd->PortCfg.CMTimerRunning = FALSE;
// happened twice within 60 sec, AP SENDS disaccociate all associated STAs. All STA's transition to State 2
// renew GTK
GenRandom(pAd, pAd->PortCfg.MBSSID[pEntry->ApIdx].GNonce,pEntry->ApIdx);
for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++)
{
if (pAd->MacTab.Content[i].Valid == TRUE)
{
DisAssocAction(pAd, &pAd->MacTab.Content[i], SUBTYPE_DISASSOC, REASON_MIC_FAILURE);
}
}
// Further, ban all Class 3 DATA transportation for a period 0f 60 sec
// disallow new association , too
pAd->PortCfg.MBSSID[pEntry->ApIdx].BANClass3Data = TRUE;
}
}while(FALSE);
RTMPAddTimer(&pAd->PortCfg.CounterMeasureTimer, 60*MLME_TASK_EXEC_INTV);
pAd->PortCfg.CMTimerRunning = TRUE;
pAd->PortCfg.PrevaMICFailTime = pAd->PortCfg.aMICFailTime;
pAd->PortCfg.aMICFailTime = jiffies;
}
/*
==========================================================================
Description:
This is state machine function.
When receiving EAPOL packets which is for 802.1x key management.
Use both in WPA, and WPAPSK case.
In this function, further dispatch to different functions according to the received packet. 3 categories are :
1. normal 4-way pairwisekey and 2-way groupkey handshake
2. MIC error (Countermeasures attack) report packet from STA.
3. Request for pairwise/group key update from STA
Return:
==========================================================================
*/
VOID WpaEAPOLKeyAction(
IN PRTMP_ADAPTER pAdapter,
IN MLME_QUEUE_ELEM *Elem)
{
INT i;
MAC_TABLE_ENTRY *pEntry;
KEY_DESCRIPTER *pKeyDesc;
PHEADER_802_11 pHeader;
PEAPOL_PACKET pMsg;
UCHAR Offset = 0;
DBGPRINT(RT_DEBUG_TRACE, "WpaEAPOLKeyAction ===> \n");
pHeader = (PHEADER_802_11)Elem->Msg;
if (pHeader->FC.SubType & 0x08)
Offset += 2;
pMsg = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H + Offset];
pKeyDesc = (PKEY_DESCRIPTER)&Elem->Msg[LENGTH_802_11+LENGTH_802_1_H+LENGTH_EAPOL_H+Offset];
#ifdef BIG_ENDIAN
// pMsg->KeyDesc.Keyinfo and pKeyDesc->Keyinfo both point to the same addr.
// Thus, it only needs swap once.
{
USHORT tmpKeyinfo;
NdisMoveMemory(&tmpKeyinfo, &pMsg->KeyDesc.Keyinfo, sizeof(USHORT));
tmpKeyinfo = SWAP16(tmpKeyinfo);
NdisMoveMemory(&pMsg->KeyDesc.Keyinfo, &tmpKeyinfo, sizeof(USHORT));
}
// *(USHORT *)&pMsg->KeyDesc.Keyinfo = SWAP16(*(USHORT *)&pMsg->KeyDesc.Keyinfo);
#endif
pEntry = MacTableLookup(pAdapter, pHeader->Addr2);
if (!pEntry)
return;
if ((pEntry->AuthMode != Ndis802_11AuthModeWPA) && (pEntry->AuthMode != Ndis802_11AuthModeWPAPSK)
&& (pEntry->AuthMode != Ndis802_11AuthModeWPA2) && (pEntry->AuthMode != Ndis802_11AuthModeWPA2PSK))
return;
if (((pMsg->ProVer!= EAPOL_VER) && (pMsg->ProVer!= EAPOL_VER2)) || ((pMsg->KeyDesc.Type != WPA1_KEY_DESC) && (pMsg->KeyDesc.Type != WPA2_KEY_DESC)))
{
DBGPRINT(RT_DEBUG_ERROR, "Key descripter does not match with WPA rule \n");
return;
}
if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled) && (pMsg->KeyDesc.Keyinfo.KeyDescVer != DESC_TYPE_AES))
{
DBGPRINT(RT_DEBUG_ERROR, "Key descripter version not match AES \n");
return;
}
else if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) && (pMsg->KeyDesc.Keyinfo.KeyDescVer != DESC_TYPE_TKIP))
{
DBGPRINT(RT_DEBUG_ERROR, "Key descripter version not match TKIP \n");
return;
}
if ((pEntry->Sst == SST_ASSOC) && (pEntry->WpaState >= AS_INITPSK))
{
if ((pEntry->GTKState == REKEY_ESTABLISHED) && (pKeyDesc->Keyinfo.KeyMic) && (pKeyDesc->Keyinfo.Secure) && !(pKeyDesc->Keyinfo.Error))
{
RTMPHandleSTAKey(pAdapter, pEntry, Elem);
}
else if ((pKeyDesc->Keyinfo.KeyMic) && (pKeyDesc->Keyinfo.Error) && (pKeyDesc->Keyinfo.Request))
{
// Category 2.
DBGPRINT(RT_DEBUG_TRACE, "MIC, ERROR, REQUEST ALL 1'S, ACTIVE COUNTERMEASURE \n");
HandleCounterMeasure(pAdapter, pEntry);
}
else if ((pKeyDesc->Keyinfo.Secure) && !(pKeyDesc->Keyinfo.Error) && !(pKeyDesc->Keyinfo.Request))
{
#ifdef BIG_ENDIAN
// recovery original byte order, before forward Elem to another routine
{
USHORT tmpKeyinfo;
NdisMoveMemory(&tmpKeyinfo, &pMsg->KeyDesc.Keyinfo, sizeof(USHORT));
tmpKeyinfo = SWAP16(tmpKeyinfo);
NdisMoveMemory(&pMsg->KeyDesc.Keyinfo, &tmpKeyinfo, sizeof(USHORT));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?