📄 eapol.cpp
字号:
// This function is defined by the standard (8.5.10.1.3(d)), and sends an
// EAP Response Authentication frame.
int txRspAuth(int prevId, int revId)
{
const int mac_header_size = 14;
u_char *resp_out=NULL;
int resp_out_size=0, i=0;
u_char *src_mac = NULL;
u_char *tmp = NULL;
resp_out = (u_char *)malloc(1514); // Again, this is the largest frame we can send.
memcpy(resp_out, eapol_dst, 6);
src_mac = get_src_mac();
memcpy(&resp_out[6], src_mac, 6);
resp_out[12] = 0x88; // 0x888e for EAPOL
resp_out[13] = 0x8e;
free(src_mac);
src_mac = NULL;
tmp = get_working_frame(); // This should be the request frame.
i = (((u_char) tmp[16] << 8) | (u_char)tmp[17]);
// Pass in the frame, minus the header.
if (eap_build_auth_response(&tmp[14], i, resp_out, &resp_out_size) == -1)
{
resp_out = NULL;
return -1;
}
else
{
send_frame(resp_out, resp_out_size);
free(resp_out);
resp_out = NULL;
}
return 0;
}
void eapol_pae_set_state(EapolStates newState)
{
// Set the last state to the current state
eapol_last_state = eapol_current_state;
//Set the current state to a new state
eapol_current_state = newState;
}
int eapol_pae_do_state()
{
int retVal = 0;
if (get_initialize())
{
eapol_pae_set_state(DISCONNECTED);
}
else if (get_eapSuccess() && !get_initialize())
{
eapol_pae_set_state(AUTHENTICATED);
xsupplicant_run_auth = 1;
}
else if(get_eapFail() && !get_initialize() && !get_userLogoff() && !get_logoffSent())
{
eapol_pae_set_state(HELD);
}
else if((get_userLogoff() && !get_logoffSent()) && !(get_initialize()))
{
eapol_pae_set_state(LOGOFF);
}
switch(eapol_get_current_state()) {
case CONNECTING:
// If we just transitioned to Connecting, we need to set the variables.
// otherwise, we need to decrement, and possibly send an EAPOL-Start.
if (eapol_get_last_state() != CONNECTING)
{
set_startWhen(startPeriod);
set_startCount(0);
set_reqId(FALSE);
txStart();
}
else
{
set_startWhen(get_startWhen() - 1);
if (get_startWhen() <= 0)
{
set_startCount(get_startCount() + 1);
set_startWhen(startPeriod);
if ((get_startCount() < 3))
{
txStart();
}
else
{
eapol_pae_set_state(AUTHENTICATED);
xsupplicant_run_auth = 1;
eapol_pae_transition_state(); // This may not be needed.
}
}
}
break;
case AUTHENTICATED:
set_eapSuccess(FALSE);
set_eapFail(FALSE);
set_suppStatus(AUTHORIZED);
break;
case ACQUIRED:
if (get_reqId() == TRUE) // Do we have an ID request?
{
txRspId(get_previousId(), get_receivedId());
set_authWhile(authPeriod);
set_startCount(0);
set_reqId(FALSE);
set_reqAuth(FALSE);
}
if (get_authWhile() <= 0)
{
set_authWhile(authPeriod);
txRspId(get_previousId(), get_receivedId());
}
else
{
set_authWhile(get_authWhile() - 1);
}
set_previousId(get_receivedId());
break;
case AUTHENTICATING:
if (get_reqAuth())
{
set_authWhile(authPeriod);
set_reqAuth(FALSE);
if (txRspAuth(get_previousId(), get_receivedId()) < 0)
{
return -1;
}
}
if (get_authWhile() <= 0)
{
set_authWhile(authPeriod);
if (txRspAuth(get_previousId(), get_receivedId()) < 0) return -1;
}
set_previousId(get_receivedId());
break;
case HELD:
if(eapol_get_current_state() != eapol_get_last_state())
{
set_heldWhile(heldPeriod);
set_eapFail(FALSE);
set_eapSuccess(FALSE);
set_suppStatus(UNAUTHORIZED);
}
else
{
if (get_heldWhile() <= 0) // We need to transition back to CONNECTING
{
eapol_pae_set_state(CONNECTING);
}
else
{
set_heldWhile(get_heldWhile() - 1);
}
}
break;
case LOGOFF:
//Send a logoff
txLogoff();
set_logoffSent(TRUE);
set_suppStatus(UNAUTHORIZED);
break;
case DISCONNECTED:
/* The 802.1x spec calls for an unconditional transition to CONNECTING from DISCONNECTED state */
set_eapSuccess(FALSE);
set_eapFail(FALSE);
set_startCount(0);
set_logoffSent(FALSE);
set_previousId(256);
set_suppStatus(UNAUTHORIZED);
set_initialize(0);
eapol_pae_set_state(CONNECTING); /* automatic transition because
We already setup link */
/* xsupplicant-specifc stuff */
set_haveKey(FALSE);
break;
default:
retVal = -1;
break;
}
if(eapol_get_current_state() != eapol_last_state)
{
eapol_last_state = eapol_get_current_state();
}
set_tick(FALSE); //Set our tick to false as the last thing we do.
// Section (8.5.3.1.1)
return retVal;
}
int eapol_pae_transition_state()
{
int retVal = 0;
switch(eapol_get_current_state())
{
case CONNECTING:
if (get_reqId() == TRUE)
{
eapol_pae_set_state(ACQUIRED);
}
break;
case ACQUIRED:
if (get_reqId() == TRUE)
{
eapol_pae_set_state(ACQUIRED);
}
else if (get_reqAuth() == TRUE)
{
eapol_pae_set_state(AUTHENTICATING);
}
else if (get_authWhile() == 0)
{
eapol_pae_set_state(CONNECTING);
}
break;
case AUTHENTICATING:
if (get_reqId() == TRUE)
{
eapol_pae_set_state(ACQUIRED);
}
else if (get_reqAuth() == TRUE)
{
eapol_pae_set_state(AUTHENTICATING);
}
else if (get_authWhile() == 0)
{
eapol_pae_set_state(CONNECTING);
}
break;
case HELD:
if (get_heldWhile() == 0)
{
eapol_pae_set_state(CONNECTING);
}
if (get_reqId() == TRUE)
{
eapol_pae_set_state(ACQUIRED);
}
break;
case AUTHENTICATED:
if (get_reqId() == TRUE)
{
eapol_pae_set_state(ACQUIRED);
}
break;
case LOGOFF:
if(!get_userLogoff())
{
eapol_pae_set_state(DISCONNECTED);
}
break;
case DISCONNECTED:
/* 802.1x specifies that you must unconditionally transition from
DISCONNECTED to CONNECTED, but we handle this in eap_pae_do_state()
in the DISCONNECTED case. */
break;
}
return retVal;
}
u_char *
eapol_create_start_stop_frame(char stst)
{
u_char *eapol_start;
u_char *src_addr;
eapol_start = (u_char *)malloc(18); // An eapol start frame is 18 bytes.
memcpy(eapol_start, eapol_dst, 6); // Copy the destination address.
src_addr = get_src_mac();
memcpy(&eapol_start[6], src_addr, 6); // Copy the source address.
free(src_addr);
src_addr = NULL;
eapol_start[12] = 0x88; // 0x888e is EAPOL frame type.
eapol_start[13] = 0x8e;
eapol_start[14] = 1; // EAPOL_Version
eapol_start[15] = stst; // Start or Stop
eapol_start[16] = 0; // No payload.
eapol_start[17] = 0;
return eapol_start;
}
int
eapol_decode_packet(u_char *in)
{
struct eth_hdr * ethHeader = (struct eth_hdr *)in;
/* The eapol header portion */
struct eapol_hdr * theHeader = (struct eapol_hdr *)(in + ETH_HDR_LEN);
/* Just the payload */
u_char * payload = in + ETH_HDR_LEN + sizeof(struct eapol_hdr);
int receive_packet_size;
struct eap_type_hdr *theTypeHeader = (struct eap_type_hdr *)payload;
/* The payload size */
int retVal = 0; /* default to success */
int eap_return = 0;
u_char *my_src = NULL;
#ifdef NAK_SUPPORT
char *temp = NULL;
#endif
/* Major confusion going on here --- figure out this packet len crap */
receive_packet_size = (int)ntohs(theHeader->len) +
sizeof(struct eapol_hdr);
my_src = get_src_mac();
if (memcmp(&in[6], my_src, ETH_ADDR_LEN) == 0)
{
free(my_src);
my_src = NULL;
return 0;
}
free(my_src);
my_src = NULL;
if (memcmp(eapol_dst, ðHeader->eth_src, ETH_ADDR_LEN) != 0)
{
// If the destination host from the authenticator isn't us, then
// don't change it.
if (memcmp(eapol_dst, ðHeader->eth_dst, ETH_ADDR_LEN) != 0)
{
memcpy(eapol_dst, bssid, ETH_ADDR_LEN);
}
/* need to update what network we are on */
}
else
{
set_initialize(0);
}
/* first set flags based on the incoming PDU */
switch (theHeader ->eaptype)
{
case EAP_PACK_TYPE:
/* See what EAP thinks about the packet-
EAP knows whether or not to send a respId so the state machine will
remain consistent, but this isn't really necessary */
set_receivedId(theTypeHeader->id);
eap_return = eap_decode_packet(in);
switch (eap_return)
{
case -1:
retVal = -1;
goto eapol_decode_packet_END;
break;
case 0: // Here, we need to check and see if the EAP type we want is being used.
set_reqAuth(TRUE);
break;
case 1:
set_reqId(TRUE);
break;
case 3:
set_eapSuccess(TRUE);
break;
case 4:
set_eapFail(TRUE);
eapol_pae_set_state(HELD);
break;
}
/* DO the stuff here to put together the return packet, given the
payload from eap_decode */
break;
case EAPOL_START:
//We will probably see EAPOL-Start messages from other clients in a
// shared media configuration. (Such as wireless) We should just
// ignore them.
retVal = 0;
goto eapol_decode_packet_END;
break;
case EAPOL_LOGOFF:
//We will probably see EAPOL-Logoff messages from other clients in a
// shared media configuration. (Such as wireless) We should just
// ignore them.
retVal = 0;
goto eapol_decode_packet_END;
break;
case EAPOL_KEY:
set_rxKey(TRUE);
break;
case EAPOL_ASF_ALERT:
break;
default:
return -1;
}
eapol_decode_packet_END:
return retVal;
}
int eapol_wireless_get_ssid(char *devname, char *retssid)
{
retssid = NULL;
return -1;
}
int
eapol_wireless_get_bssid(char *device, u_char *bssid)
{
int skfd; /* the socket */
struct iwreq wrq;
/* Get a socket */
skfd = socket(AF_INET, SOCK_DGRAM, 0);
strncpy(wrq.ifr_name, device, IFNAMSIZ);
memcpy(bssid, wrq.u.ap_addr.sa_data, 6);
close(skfd);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -