📄 eap.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 <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <winsock2.h>
#include "dot1x_globals.h"
#include "os_frame_funcs.h"
#include "eap.h"
#include "eapmd5.h"
#include "userconf.h"
#ifndef EAP_DEBUG
#define EAP_DEBUG 0
#endif
/** GLOBAL VARS **/
int eap_auth_types[] = {
EAP_TYPE_MD5,
NO_EAP_AUTH
};
char *eap_auth_names[] = {
"MD5",
};
int (*eap_auth_inits[])(char *, char *) = {
init_eapmd5,
};
int (*eap_auth_challenge[])() = {
eapmd5_auth_challenge,
};
int (*eap_auth_handlers[])(u_char *, int, u_char *, int *) = {
eapmd5_decode_packet,
};
int (*eap_auth_cleanup[])() = {
eapmd5_shutdown,
};
char *eap_config;
char *eap_netid;
/** FUNCTION DEFINITIONS **/
int init_eap(char *config, char *netid)
{
int auth = 0;
eap_config = config;
eap_netid = netid;
/* Initialize Auth types */
while (eap_auth_types[auth] != NO_EAP_AUTH)
{
if ((*eap_auth_inits[auth++])(config, netid) != 0)
{
printf("Couldn't initalize eap type : %s\n", eap_auth_names[auth]);
printf("If you are trying to use this authentication method, it probably won't work!\n");
}
}
return 0;
}
//Check to see if we have a valid EAP type. (If so, return the auth index.)
int is_valid_eap(char *in_eap)
{
int auth=0;
while ((strncmp(eap_auth_names[auth], in_eap, strlen(in_eap) != 0)) &&
(eap_auth_types[auth] != NO_EAP_AUTH))
{
// We don't have a match. Check the next one.
auth++;
}
if (eap_auth_types[auth] != NO_EAP_AUTH)
{
return eap_auth_types[auth];
}
return -1; // We didn't find a match.
}
// Return a list of known EAP types.
char *return_known_eap_types()
{
int auth = 0;
char *eap_types;
int eap_size=0;
int num_types=0;
char *comma_space = ", ";
char *period = ".";
while (eap_auth_types[auth] != NO_EAP_AUTH)
{
eap_size+=strlen(eap_auth_names[auth]);
eap_size+=2; // for a comma and space.
auth++;
num_types++;
}
auth = 0;
eap_types = (char *)malloc(eap_size); // Build a string big enough.
eap_types[0] = 0x00; // Set the first character to a NULL.
while (eap_auth_types[auth] != NO_EAP_AUTH)
{
strcat(eap_types, eap_auth_names[auth]);
if (auth < (num_types-1))
{
strcat(eap_types, comma_space);
}
else
{
strcat(eap_types, period);
}
auth++;
}
return eap_types;
}
// Call the shutdown routines for all of the authentication types.
int shutdown_eap()
{
int auth = 0;
while (eap_auth_types[auth] != NO_EAP_AUTH)
{
(* eap_auth_cleanup[auth++])();
}
return 0;
}
// Here, we want to actually build a responseId.
int eap_build_responseId(u_char *out, int *out_size)
{
const int eap_header_size = 5;
char *temp_buf = NULL;
int temp_size;
struct my_eapol_header *eapol_header = (struct my_eapol_header *)out;
struct my_eapol_packet *eapol_packet = (struct my_eapol_packet *)out;
/* XXX Really, I would like to see us reparse here for the right network,
but for now I am just checking to see we dont' segfault */
temp_buf = get_username();
if (temp_buf == NULL)
return -1;
temp_size = strlen(temp_buf); // The username is appended to the frame.
// So, we need to know how long it is.
// Set up the EAP values needed for the frame.
eapol_header->eapol_version = 1;
eapol_header->eapol_type = EAPOL_PACKET;
// The length value that is reported in the frame is the length of the EAP
// portion only. So, the actual size of the frame will be 18 bytes larger.
// 12 (src/dst MAC) + 2 (EAPOL Frame Type) + 4 (EAPOL Header)
eapol_header->eapol_length = htons(eap_header_size+temp_size);
eapol_packet->code = EAP_RESPONSE;
eapol_packet->identifier = get_receivedId();
eapol_packet->length = eapol_header->eapol_length;
eapol_packet->type = EAP_TYPE_ID;
// At offset 23 in to the frame, we should have non-header data, such as
// the username. Copy the username in to the frame.
memcpy(&out[EAP_PAYLOAD_OFFSET], temp_buf, temp_size);
// out_size should be the size of the data we created here. Ignore the
// additional MAC header bytes, as they will be added by the calling function
*out_size = EAP_PAYLOAD_OFFSET+temp_size;
return 0;
}
// Build the frame that will carry our authentication response.
//
int eap_build_auth_response(u_char *in, int in_size, u_char *out, int *out_size)
{
const int eapol_header_size = 5;
int auth=0;
u_char *temp_buf=NULL;
u_char *payload = in + 9; // This is the first byte in the payload.
struct my_eapol_header *eapol_header = (struct my_eapol_header *)out;
struct my_eapol_packet *eapol_packet = (struct my_eapol_packet *)out;
// This is the offset to get past the MAC header.
int payload_size = in_size - 9; // This is the payload size, minus all headers.
int temp_size;
// First, see if we have a handler for this case.
while ((eap_auth_types[auth] != get_authType()) && (eap_auth_types[auth] != NO_EAP_AUTH))
auth++;
if (eap_auth_types[auth] == NO_EAP_AUTH)
{
return -1;
}
// Now, determine if this is our first authentication, or if we are
// reauthenticating.
if (get_suppStatus() != AUTHORIZED)
{
// We need to get a password, or some other authentication information.
if ((eap_auth_challenge[auth])() < 0)
{
return -1;
}
}
// Now, build the authentication answer. (Allocate 1500 bytes, since our
// ethernet MTU is 1514, but we aren't dealing with the 14 bytes for header.)
temp_buf = (u_char *)malloc(1500);
if ((* eap_auth_handlers[auth])(payload, payload_size, temp_buf, &temp_size) == -1) {
return -1;
}
eapol_header->eapol_version = 1;
eapol_header->eapol_type = EAPOL_PACKET;
eapol_header->eapol_length = htons(eapol_header_size+temp_size); //Make sure we have the correct byte order.
eapol_packet->code = EAP_RESPONSE;
eapol_packet->identifier = get_receivedId();
eapol_packet->length = eapol_header->eapol_length;
eapol_packet->type = eap_auth_types[auth];
memcpy(&out[EAP_PAYLOAD_OFFSET], temp_buf, temp_size);
free(temp_buf); //We no longer need temp_buf
*out_size = EAP_PAYLOAD_OFFSET+temp_size;
return 0;
}
int eap_decode_packet(u_char *in)
{
struct my_eapol_packet * mypacket = (struct my_eapol_packet *)(in);
int retVal = 0;
/* USE #defines here because the struct is not the same size as the
actual header (padding) */
/* decode based on the EAP code */
switch(mypacket->code) {
case EAP_REQUEST:
switch(mypacket->type) {
case EAP_TYPE_ID:
retVal = 1;
break;
case EAP_TYPE_NOTIFY:
printf("Received EAP Notify\n");
break;
case EAP_TYPE_NAK:
printf("Received EAP NAK\n");
break;
default:
set_authType(mypacket->type);
retVal = 0;
}
break;
case EAP_RESPONSE:
printf("received EAP_RESPONSE packet -- error\n");
retVal = 0; // We should return an error here, but if we do the current code will cause the supplicant to die.
break;
case EAP_SUCCESS:
retVal = 3;
break;
case EAP_FAILURE:
retVal = 4;
break;
default:
printf("Unknown EAP code type\n");
}
return retVal;
}
/*** EOF ***/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -