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 + -
显示快捷键?