📄 peap_phase2.c
字号:
/** * A client-side 802.1x implementation * * 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. *//******************************************************************* * The driver function for a Linux application layer EAPOL * implementation * File: peap_phase2.c * * Authors: Chris.Hessing@utah.edu * * $Id: peap_phase2.c,v 1.19 2004/07/15 04:15:37 chessing Exp $ * $Date: 2004/07/15 04:15:37 $ * $Log: peap_phase2.c,v $ * Revision 1.19 2004/07/15 04:15:37 chessing * * True/false int values are now bit flags in a byte. PEAP now calls back in to functions from eap.c for phase 2 methods. This allows for any phase 1 EAP type to work. This resulted in some major changes the functions in eap.c, and in peap_phase2.c. PEAP has been tested using both MS-CHAPv2, and EAP-MD5 as inner types. More types need to be tested, and enabled. * * Revision 1.18 2004/06/29 01:35:36 chessing * * Added credit to eapleap.c for Gilbert Goodwill (who gave me the clues I needed to figure out the keying piece for LEAP). Added patch from Toby Collett to make PEAP work for broken implementations of IAS. (New option ias_quirk has been added.) * * Revision 1.17 2004/06/15 03:22:31 chessing * * XSupplicant Release 1.0 * * *******************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <netinet/in.h>#include "config.h"#include "profile.h"#include "eap.h"#include "peap_phase2.h"#include "eappeap.h"#include "../tls/eaptls.h"#include "xsup_err.h"#include "xsup_debug.h"#include "../mschapv2/eapmschapv2.h"#include "../otp/eapotp.h"#include "../tls/tls_crypt.h"#define VALID_EAP_TYPE EAP_TYPE_MSCHAP#define HIGHEST_PEAP_SUPPORTED 1int set_peap_version(struct phase2_data *p2d, int new_version){ if (!p2d) { debug_printf(DEBUG_NORMAL, "Invalid phase 2 data in set_peap_version()!\n"); return XEMALLOC; } if (new_version > HIGHEST_PEAP_SUPPORTED) { p2d->peap_version = HIGHEST_PEAP_SUPPORTED; return HIGHEST_PEAP_SUPPORTED; } // Only change versions if we are changing to a higher one. This will // keep us from backing off to a lower version mid-communication, should the // RADIUS server get confused. if (p2d->peap_version < new_version) { debug_printf(DEBUG_AUTHTYPES, "PEAP Version changed to %d\n",new_version); p2d->peap_version = new_version; } return p2d->peap_version;}// Remove the beginning 18 bytes.void peap_unpad_frame(u_char *in, int in_size, u_char *out, int *out_size){ int i; if ((!in) || (!out)) { debug_printf(DEBUG_NORMAL, "Invalid packet buffer in in or out at peap_unpad_frame()!\n"); return; } if (in_size > 1520) { debug_printf(DEBUG_NORMAL, "Packet too large in peap_unpad_frame()!\n"); return; } *out_size = in_size - 4; for (i=0;i<=*out_size;i++) { out[i] = in[4+i]; }}// Pad out the beginning with 18 bytes. (Probably 0s.)void peap_pad_frame(u_char *in, int in_size, u_char *out, int *out_size){ int i; if ((!in) || (!out)) { debug_printf(DEBUG_NORMAL, "Invalid packet buffer in in or out at peap_pad_frame()!\n"); return; } if (in_size > 1520) { debug_printf(DEBUG_NORMAL, "In packet size to large! Ignoring!\n"); return; } *out_size = in_size + 4; bzero(out, *out_size); for (i=0;i<=in_size;i++) { out[4+i] = in[i]; }}void do_peap_version1(struct phase2_data *thisint, u_char *in, int in_size, u_char *out, int *out_size){ char *new_frame = NULL; int eapvalue, eapid; struct tls_vars *mytls_vars; if ((!thisint) || (!out) || (!out_size)) { debug_printf(DEBUG_NORMAL, "Invalid data passed in to do_peap_version1()!\n"); if (out_size) *out_size = 0; return; } if (in_size > 1520) { debug_printf(DEBUG_NORMAL, "Invalid frame passed in to do_peap_version1()!\n"); return; } *out_size = 0; mytls_vars = (struct tls_vars *)thisint->eapdata->eap_data; // mytls_vars may be NULL here! This is okay, as long as we aren't in the // middle of an inner authentication. eapvalue = in[4]; eapid = in[5]; // Inner EAP id. debug_printf(DEBUG_AUTHTYPES, "Inner packet : \n"); if (in_size < 1522) { debug_hex_dump(DEBUG_AUTHTYPES, in, in_size); } else { debug_printf(DEBUG_AUTHTYPES, "INVALID PACKET SIZE!\n"); } new_frame = (char *)malloc(1024); if (new_frame == NULL) { debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for new_frame in do_peap_version1()!\n"); return; } bzero(new_frame, 1024); switch ((uint8_t)eapvalue) { case EAP_REQUEST: eap_request_id(thisint->eapdata->identity, eapid, out, out_size); break; case EAP_SUCCESS: printf("Got a phase 2 success!\n"); break; // If we catch the EAP_FAILURE, it has the same value as MD5. Which // is probably why PEAP-EAP-MD5 isn't allowed in XP. ;) /* case EAP_FAILURE: printf("Got a phase 2 failure!\n"); break; */ case PEAP_EAP_EXTENSION: // EAP Extension debug_printf(DEBUG_AUTHTYPES, "Got an EAP extension frame!\n"); out[0] = EAP_RESPONSE; memcpy(&out[1], &in[1], in_size-1); *out_size = in_size; break; default: if (eap_create_active_method(&thisint->activemethod, thisint->eapdata->identity, thisint->eapdata->tempPwd) != 0) { debug_printf(DEBUG_NORMAL, "Couldn't build active method! Phase 2 authentication will not happen!\n"); return; } eap_request_auth(thisint->activemethod, thisint->eapdata->eap_conf_data, in, in_size, out, out_size); break; } free(new_frame);}void do_peap_version0(struct phase2_data *thisint, u_char *in, int in_size, u_char *out, int *out_size){ char *padded_frame, *new_frame; int padded_size, new_frame_size, eframe = 0; if ((!thisint) || (!out_size)) { debug_printf(DEBUG_NORMAL, "Invalid data passed in to do_peap_version0()!\n"); if (out_size) *out_size = 0; return; } *out_size = 0; if (!in) { debug_printf(DEBUG_NORMAL, "Input frame was NULL! Ignoring!\n"); return; } if (!out) { debug_printf(DEBUG_NORMAL, "Invalid return buffer!\n"); return; } if (in_size>1520) { debug_printf(DEBUG_NORMAL, "Input frame is too big! Ignoring!\n"); *out_size = 0; return; } padded_size = in_size; padded_frame = (char *)malloc(in_size+19); // It is 19 bytes to pad out. if (padded_frame == NULL) { debug_printf(DEBUG_NORMAL, "Unable to allocate memory for padded_frame in do_peap_version0()!\n"); return; } if ((in[4] == 0x21) && (in[5] = 0x80) && !(thisint->eapdata->ias_quirk == 1 && in[0] == EAP_TYPE_MSCHAPV2)) { eframe = 1; memcpy(padded_frame, in, in_size); } if (eframe != 1) { peap_pad_frame(in, in_size, padded_frame, &padded_size); } new_frame = (char *)malloc(1024); if (new_frame == NULL) { debug_printf(DEBUG_NORMAL, "ACK! We can't allocate memory!\n"); return; } do_peap_version1(thisint, padded_frame, padded_size, new_frame, &new_frame_size); free(padded_frame); if (eframe !=1) { peap_unpad_frame(new_frame, new_frame_size, out, out_size); } else { memcpy(out, new_frame, new_frame_size); *out_size = new_frame_size; } free(new_frame); eframe = 0;}void peap_do_phase2(struct generic_eap_data *thisint, u_char *in, int in_size, u_char *out, int *out_size){ struct tls_vars *mytls_vars; struct phase2_data *p2d; u_char *decr_data, *encr_data; int encrsize, decrsize; struct config_eap_peap *peapconf; struct generic_eap_data *eapdata; if ((!thisint) || (!in) || (!out)) { debug_printf(DEBUG_NORMAL, "Invalid parameters passed in to peap_do_phase2()!\n"); return; } *out_size = 0; mytls_vars = (struct tls_vars *)thisint->eap_data; if (mytls_vars == NULL) { debug_printf(DEBUG_NORMAL, "mytls_vars (thisint->eap_data) == NULL!\n"); return; } peapconf = (struct config_eap_peap *)thisint->eap_conf_data; if (peapconf == NULL) { debug_printf(DEBUG_NORMAL, "peapconf == NULL!\n"); return; } p2d = (struct phase2_data *)mytls_vars->phase2data; if (p2d->eapdata == NULL) { p2d->eapdata = (struct generic_eap_data *)malloc(sizeof(struct generic_eap_data)); if (p2d->eapdata == NULL) { *out_size = 0; return; } memset(p2d->eapdata, 0, sizeof(struct generic_eap_data)); p2d->eapdata->eap_data = NULL; } p2d->eapdata->eap_conf_data = peapconf->phase2; p2d->eapdata->identity = thisint->identity; p2d->eapdata->ias_quirk = peapconf->ias_quirk; decr_data = (char *)malloc(1550); if (decr_data == NULL) { debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for decryption buffer!\n"); return; } encr_data = (char *)malloc(1550); if (encr_data == NULL) { debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for encryption buffer!\n"); free(decr_data); return; } if (in_size > 0) { tls_crypt_decrypt(thisint, in, in_size, decr_data, &decrsize); debug_printf(DEBUG_AUTHTYPES, "Decrypted dump : \n"); debug_hex_dump(DEBUG_AUTHTYPES, decr_data, decrsize); } else { free(decr_data); decr_data = NULL; } // We need to check this. I don't think it is needed anymore. if (decrsize <=0) { debug_printf(DEBUG_AUTHTYPES, "Sending ACK!\n"); bzero(out,10); *out_size = 1; free(decr_data); free(encr_data); return; } debug_printf(DEBUG_AUTHTYPES, "Decrypted packet returned %d byte(s)\n", decrsize); if (thisint->tempPwd != NULL) { eapdata = p2d->eapdata; if (eapdata != NULL) { eapdata->tempPwd = thisint->tempPwd; } } bzero(out, 100); switch (p2d->peap_version) { case 0: debug_printf(DEBUG_AUTHTYPES, "Doing PEAP v0!\n"); do_peap_version0(p2d, decr_data, decrsize, encr_data, &encrsize); break; case 1: debug_printf(DEBUG_AUTHTYPES, "Doing PEAP v1!\n"); do_peap_version1(p2d, decr_data, decrsize, encr_data, &encrsize); break; default: debug_printf(DEBUG_NORMAL, "Unknown PEAP version! (%d)\n",p2d->peap_version); break; } eapdata = p2d->eapdata; if (eapdata->need_password == 1) { thisint->need_password = 1; thisint->eaptype = eapdata->eaptype; thisint->eapchallenge = eapdata->eapchallenge; *out_size = 0; } if (encrsize > 0) { debug_printf(DEBUG_AUTHTYPES, "Unencrypted return frame : \n"); debug_hex_dump(DEBUG_AUTHTYPES, encr_data, encrsize); tls_crypt_encrypt_nolen(thisint, encr_data, encrsize, out, out_size); debug_printf(DEBUG_AUTHTYPES, "Encrypted return frame : \n"); debug_hex_dump(DEBUG_AUTHTYPES, out, *out_size); } free(encr_data); free(decr_data);}void peap_phase2_failed(struct generic_eap_data *thisint){ struct tls_vars *mytls_vars; struct phase2_data *p2d; if (!thisint) { debug_printf(DEBUG_NORMAL, "Invalid data passed to peap_phase2_failed()!\n"); return; } mytls_vars = (struct tls_vars *)thisint->eap_data; if (mytls_vars == NULL) { debug_printf(DEBUG_NORMAL, "mytls_vars (thisint->eap_data) == NULL!\n"); return; } p2d = (struct phase2_data *)mytls_vars->phase2data; if (p2d->eapdata == NULL) { // We didn't get to phase 2, so just bail. return; } eap_do_fail(p2d->activemethod);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -