📄 eapol.cpp
字号:
/**************************************************************************/
/* WIRE1x Version 1.0: A client-side 802.1x implementation */
/* based on xsupplicant of Open1x for Windows XP, 2000, 98, and Me */
/* */
/* This code is released under both the GPL version 2 and BSD licenses. */
/* Either license may be used. The respective licenses are found below. */
/* */
/* Copyright (C) 2004, WIRE Lab, National Tsing Hua Univ., Hsinchu, Taiwan*/
/* All Rights Reserved */
/**************************************************************************/
/** * A client-side 802.1x implementation supporting EAP/TLS * * This code is released under both the GPL version 2 and BSD licenses. * Either license may be used. The respective licenses are found below. * * Copyright (C) 2002 Bryan D. Payne & Nick L. Petroni Jr. * All Rights Reserved * * --- GPL Version 2 License --- * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * --- BSD License --- * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * Maryland at College Park and its contributors. * - Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *//*** *** Specifics for EAPOL can be found in Section 7 of *** IEEE Draft P802.1X/D11, ***/#include <stdafx.h>
#include <string.h>#include <pcap.h>
#include <libnet.h>#include <unistd.h>#include <errno.h>#include <stdlib.h>
#include <signal.h>#include "dot1x_globals.h"
#include "eapol.h"#include "os_frame_funcs.h"#include "os_wireless_ext.h"#include "userconf.h"#ifndef EAPOL_DEBUG#define EAPOL_DEBUG 0#endif #define NAK_SUPPORT // FreeRadius doesn't support this!/** GLOBAL VARS **/// moved to 802.1x spec. globals to dot1x_globals.hunsigned int successCount = 0;unsigned int failCount = 0;/* IEEE 802.1x default recommendations *//* Note that these don't need to be strict consts *//* IEEE 802.1x specifies that the state machine shouldn't *//* modify these values, so in that way, they are const, but not otherwise */const int authPeriod = 30;const int heldPeriod = 60;const int startPeriod = 30;const int maxStart = 3;/* Globals for this specific implementation */u_char *eapol_src = NULL; /* MAC address of interface */
u_char ETH_HDR_LEN = 14 ;
u_char eapol_dst[ETH_ADDR_LEN] ; //addu_char bssid[ETH_ADDR_LEN] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x03}; /* MAC address of authenticator */
char * eapol_device = NULL; /* Interface name */char * eapol_config = "1x.conf"; /* Configuration File */char eapol_ssid[100] = ""; /* network name */int xsupplicant_first_auth = 0;int xsupplicant_run_auth = 0;int xsupplicant_auth_command_pid = 0; // pid could never be 0EapolStates eapol_current_state = DISCONNECTED;EapolStates eapol_last_state = DISCONNECTED;KeyReceiveStates eapol_key_receive_state;
unsigned char is_wired = FALSE;
//Return the current state of the state machine.
EapolStates eapol_get_current_state()
{
return eapol_current_state;
}
CString get_current_state() //for GUI
{
CString text;
if (eapol_current_state == 0)
text="LOGOFF";
else if (eapol_current_state == 1)
text="DISCONNECTED";
else if (eapol_current_state == 2)
text="CONNECTING";
else if (eapol_current_state == 3)
text="ACQUIRED";
else if (eapol_current_state == 4)
text="AUTHENTICATING";
else if (eapol_current_state == 5)
text="HELD\n(You fail the authentication!)";
else if (eapol_current_state == 6)
text="AUTHENTICATED\n(You are authenticated successfully!)";
return text;
}
//Return the last state of the state machine.
EapolStates eapol_get_last_state()
{
return eapol_last_state;
}
int getFailCount()
{
return failCount;
}
int getSuccessCount()
{
return successCount;
}
int init_eapol(char *device, char *netid, u_char *auth_addr,
char *config)
{
int retVal = 0; /* default to success */
char *reterr; // Pointer to hold an error return code.
char *temp_char;
char *wired_type = "WIRED";
// Initalize the frame functions.
reterr = initalize_frame_funcs(device, 1700, 0);
eapol_device = get_dev_name();
if (eapol_device == NULL) return -1; //If we can't get an address name, die
printf("Setup on device %s complete\n", eapol_device);
/* setup config file */
if (config != NULL) {
}
/* set authenticator address */
if (auth_addr != NULL)
{
printf("Setting destination to : %x:%x:%x:%x:%x:%x\n", auth_addr[0],
auth_addr[1], auth_addr[2], auth_addr[3], auth_addr[4],
auth_addr[5]);
//memcpy(eapol_dst, auth_addr, ETH_ADDR_LEN);
memcpy(eapol_dst, bssid, ETH_ADDR_LEN); //Nov.27
}
else
{
temp_char = get_client_type();
if (temp_char == NULL || (strncmp(temp_char, "WIRELESS", strlen(temp_char))==0))
{
if (eapol_wireless_get_bssid(eapol_device, eapol_dst)==-1)
{
printf("Specific Wireless Authenticator MAC not found, using default destination\n");
}
/* determine network name */
if (netid != NULL)
{
strncpy(eapol_ssid, netid, 99);
if (strlen(netid) >= 100)
{
printf("Network ID too long\n");
return -1;
}
}
else if (eapol_wireless_get_ssid(eapol_device, eapol_ssid) == -1)
{
strncpy(eapol_ssid,"default\0",8);
}
}
else
{
printf("This connection has been forced to a wired connection! The network name will be 'default'\n");
strncpy(eapol_ssid,"default\0",8);
is_wired=TRUE;
}
}
/* Establish our global variables. */
set_initialize(1);
eapol_pae_transition_state(); // We need to transition to the correct state
/* initialize lower layer */
if (init_eap(eapol_config, eapol_ssid) != 0)
{
printf("Problems initalizing EAP methods!\n");
return -1;
}
printf("Done with init.\n");
return retVal;
}
void eapol_handle_logoff()
{
/* This is a kludge. We should really be checking to see
if we have an interface to pass frames to, otherwise we segfault. */
if(eapol_get_current_state() == AUTHENTICATED)
{
set_userLogoff(1);
eapol_pae_transition_state();
eapol_pae_do_state();
set_userLogoff(0);
}
}
// Clean up
int eapol_shutdown()
{
eapol_handle_logoff();
shutdown_frame_funcs();
return 0;
}
int
eapol_authenticate()
{
/* general setup */
u_char *frame_ptr = NULL;
int retVal = 0; /* default to success */
/* if we have a different bssid than previously, inititialize */
if (eapol_pae_do_state() < 0) { return -1;}
/* get the next frame */
while (frame_ptr == NULL)
{
//Check for logoff
if(get_userLogoff())
{
if(eapol_get_current_state() == LOGOFF) // We're trying to logoff... return -1
{
return -1;
}
}
// If the sleep value for get_frame is too high, we will miss frames
// and may fail the next authentication request. If the value is
// too low, we will waste a lot of processor time, and eat laptop
// batteries.
if (more_frames() == 1) // We have more frames, so don't wait before
{ // checking.
frame_ptr = get_frame(0);
}
else
{
frame_ptr = get_frame(1000); // Wait 1/4th of a second.
}
if (get_tick()==TRUE)
{
if (eapol_pae_do_state() < 0) return -1;
}
// We need to keep the event loop in 1xdriver.c going.
// If we get this far, and the frame_ptr is NULL, we should return 0;
if(frame_ptr == NULL)
{
return 0;
}
}
if (frame_ptr != NULL)
/* decode the packet and get the next response back*/
if((retVal = eapol_decode_packet(frame_ptr)) == -1)
{
return retVal;
}
/* Based on the received packet, go to the next state of each machine */
eapol_pae_transition_state();
done_with_current_frame(); // This should destroy the frame in memory.
if (frame_ptr != NULL)
{
frame_ptr = NULL;
}
return retVal;
}
void xsupplicant_shutdown_auth()
{
xsupplicant_auth_command_pid = 0;
}
void xsupplicant_post_auth()
{
char *command = NULL;
// if it's the first transition to auth
/** XXX Use something other than popen here, we really want it to die
when we close it */
if (xsupplicant_run_auth && !xsupplicant_first_auth)
{
if ((command = get_first_auth()) != NULL)
{
if (xsupplicant_auth_command_pid)
xsupplicant_shutdown_auth();
if (xsupplicant_auth_command_pid == 0 )
{
exit(0);
}
else if (xsupplicant_auth_command_pid == -1)
{
}
}
// never do that again
xsupplicant_first_auth = 1;
}
// all other transitions to auth
else if(xsupplicant_run_auth)
{
if ((command = get_after_auth()) != NULL)
{
if (xsupplicant_auth_command_pid)
xsupplicant_shutdown_auth();
if (xsupplicant_auth_command_pid == 0 )
{
exit(0);
}
else if (xsupplicant_auth_command_pid == -1)
{
}
}
}
if (command) free(command);
// unconditionally say we have done something
xsupplicant_run_auth = 0;
}
/**** LOW LEVEL FUNCTIONS****/
/* Only Functions defined in EAPOL should call these */
// This function is defined by the standard (8.5.10.1.3(a)), and sends an
// EAPOL-Start frame.
void txStart()
{
u_char *temp;
temp = eapol_create_start_stop_frame(EAPOL_START);
send_frame(temp, 18);
if (send_frame(temp, 18) == NULL)
free(temp);
temp = NULL;
}
// This function is defined by the standard (8.5.10.1.3(b)), and sends an
// EAPOL-Logoff frame.
void txLogoff()
{
u_char *temp;
temp = eapol_create_start_stop_frame(EAPOL_LOGOFF);
send_frame(temp, 18);
free(temp);
temp = NULL;
}
// This function is defined by the standard (8.5.10.1.3(c)), and sends an
// EAP Response, Identity frame.
void txRspId(int prevId, int revId)
{
const int mac_header_bytes = 14;
u_char *resp_out = NULL;
int resp_out_size = 0;
u_char *src_mac = NULL;
resp_out = (u_char *)malloc(1514); // 1514 is the largest frame we could send.
memcpy(resp_out, eapol_dst, 6);
src_mac = get_src_mac();
if(src_mac == NULL)
{
printf("ACK! src_mac is NULL in txRspId! (We're going to crash.)\n");
}
memcpy(&resp_out[6], src_mac, 6);
free(src_mac);
src_mac = NULL;
resp_out[12] = 0x88; // 0x888e is an EAPOL frame
resp_out[13] = 0x8e;
if (eap_build_responseId(resp_out, &resp_out_size) == -1)
{
free(resp_out);
resp_out = NULL;
}
else
{
send_frame(resp_out, resp_out_size);
free(resp_out);
resp_out = NULL;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -