📄 eapmschapv2.c
字号:
/** * 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. *//******************************************************************* * EAP-MSCHAPv2 Function implementations * * File: eapmschapv2.c * * Authors: Chris.Hessing@utah.edu * * $Id: eapmschapv2.c,v 1.23 2004/06/29 01:35:35 chessing Exp $ * $Date: 2004/06/29 01:35:35 $ * $Log: eapmschapv2.c,v $ * Revision 1.23 2004/06/29 01:35:35 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.22 2004/06/15 03:35:20 chessing * * New updates including fixes to LEAP (keying now works with wireless) and adding EAP-AKA. * * Revision 1.21 2004/06/15 03:22:29 chessing * * XSupplicant Release 1.0 * * *******************************************************************/#include <openssl/rand.h>#include <string.h>#include <netinet/in.h>#include "profile.h"#include "config.h"#include "xsup_debug.h"#include "xsup_err.h"#include "frame_structs.h"#include "eapmschapv2.h"#include "mschapv2.h"#include "eap.h"#include "interactive.h"int eapmschapv2_setup(struct generic_eap_data *thisint){ struct mschapv2_vars *myvars; if (!thisint) { debug_printf(DEBUG_NORMAL, "Invalid interface structure passed in to eapmschapv2_setup()!\n"); return XEMALLOC; } thisint->eap_data = (u_char *)malloc(sizeof(struct mschapv2_vars)); if (thisint->eap_data == NULL) return XEMALLOC; memset(thisint->eap_data, 0, sizeof(struct mschapv2_vars)); myvars = thisint->eap_data; myvars->AuthenticatorChallenge = NULL; myvars->PeerChallenge = NULL; myvars->NtResponse = NULL; myvars->keyingMaterial = NULL; return XENONE;}int eapmschapv2_process(struct generic_eap_data *thisint, u_char *dataoffs, int insize, u_char *outframe, int *outsize){ struct mschapv2_challenge *challenge; struct mschapv2_response *response; struct mschapv2_success_request *success; struct mschapv2_vars *myvars; char *username; int respOk; u_char recv[41]; u_char NtHash[16], NtHashHash[16], MasterKey[16]; u_char mppeSend[16], mppeRecv[16]; struct config_eap_mschapv2 *userdata; if (!thisint) { debug_printf(DEBUG_NORMAL, "Invalid interface structure passed in to eapmschapv2_process()!\n"); return XEMALLOC; } if (!outframe) { debug_printf(DEBUG_NORMAL, "Invalid return buffer in eapmschapv2_process()!\n"); return XEMALLOC; } if (!thisint->eap_conf_data) { debug_printf(DEBUG_NORMAL, "No valid configuration data available for MSCHAP-V2!\n"); return XEMALLOC; } userdata = (struct config_eap_mschapv2 *)thisint->eap_conf_data; if (!thisint->eap_data) { debug_printf(DEBUG_NORMAL, "Invalid state configuration in MSCHAP-V2!\n"); return XEMALLOC; } myvars = (struct mschapv2_vars *)thisint->eap_data; if ((thisint->tempPwd == NULL) && (userdata->password == NULL)) { thisint->need_password = 1; thisint->eaptype = strdup("EAP-MS-CHAPv2"); thisint->eapchallenge = NULL; *outsize = 0; return XENONE; } // Make sure we have something to process... if (dataoffs == NULL) return XENONE; if (userdata->username == NULL) { username = thisint->identity; } else { username = userdata->username; } if ((userdata->password == NULL) && (thisint->tempPwd != NULL)) { userdata->password = thisint->tempPwd; thisint->tempPwd = NULL; } switch ((uint8_t)dataoffs[0]) { case MS_CHAPV2_CHALLENGE: debug_printf(DEBUG_AUTHTYPES, "(EAP-MSCHAPv2) Challenge\n"); challenge = (struct mschapv2_challenge *)dataoffs; response = (struct mschapv2_response *)outframe; debug_printf(DEBUG_AUTHTYPES, "(EAP-MS-CHAPv2) ID : %02X\n", challenge->MS_CHAPv2_ID); // This value should *ALWAYS* be 16! if (challenge->Value_Size != 0x10) { if (thisint->ias_quirk == 1) { debug_printf(DEBUG_NORMAL, "(EAP-MS-CHAPv2) Invalid Value-Size! (%d), forced to 0x10 (ias_quirk=yes)\n", challenge->Value_Size); challenge->Value_Size = 0x10; } else { debug_printf(DEBUG_NORMAL, "(EAP-MS-CHAPv2) Invalid Value-Size! (%d)\n", challenge->Value_Size); debug_printf(DEBUG_NORMAL, "(EAP-MS-CHAPv2) Should you enable ias_quirk?\n"); return XEMSCHAPV2LEN; } } if (myvars->AuthenticatorChallenge != NULL) { free(myvars->AuthenticatorChallenge); myvars->AuthenticatorChallenge = NULL; } myvars->AuthenticatorChallenge = (u_char *)malloc(16); if (myvars->AuthenticatorChallenge == NULL) return XEMALLOC; memcpy(myvars->AuthenticatorChallenge, &challenge->Challenge, 16); debug_printf(DEBUG_AUTHTYPES, "Authenticator Challenge : "); debug_hex_printf(DEBUG_AUTHTYPES, myvars->AuthenticatorChallenge, 16); if (myvars->PeerChallenge != NULL) { free(myvars->PeerChallenge); myvars->PeerChallenge = NULL; } // Ignore the RADIUS host, we probably don't care. myvars->PeerChallenge = (u_char *)malloc(16); if (myvars->PeerChallenge == NULL) return XEMALLOC; RAND_bytes(myvars->PeerChallenge, 16); debug_printf(DEBUG_AUTHTYPES, "Generated PeerChallenge : "); debug_hex_printf(DEBUG_AUTHTYPES, myvars->PeerChallenge,16); if (myvars->NtResponse != NULL) { free(myvars->NtResponse); myvars->NtResponse = NULL; } myvars->NtResponse = (u_char *)malloc(24); if (myvars->NtResponse == NULL) return XEMALLOC; GenerateNTResponse(myvars->AuthenticatorChallenge, myvars->PeerChallenge, username, userdata->password, myvars->NtResponse); debug_printf(DEBUG_AUTHTYPES, "myvars->NtResponse = "); debug_hex_printf(DEBUG_AUTHTYPES, myvars->NtResponse, 24); response->OpCode = MS_CHAPV2_RESPONSE; response->MS_CHAPv2_ID = challenge->MS_CHAPv2_ID; response->MS_Length = htons(54+strlen(username)); response->Value_Size = 49; memcpy((u_char *)&response->Peer_Challenge, myvars->PeerChallenge, 16); bzero((u_char *)&response->Reserved, 8); memcpy((u_char *)&response->NT_Response, myvars->NtResponse, 24); debug_printf(DEBUG_AUTHTYPES, "response->NT_Response = "); debug_hex_printf(DEBUG_AUTHTYPES, response->NT_Response, 24); response->Flags = 0; memcpy(&outframe[54],username, strlen(username)); *outsize = (54 + strlen(username)); break; case MS_CHAPV2_RESPONSE: debug_printf(DEBUG_NORMAL, "Got an MS-CHAPv2 Response!? Ignoring.\n"); *outsize = 0; break; case MS_CHAPV2_SUCCESS: debug_printf(DEBUG_AUTHTYPES, "(EAP-MSCHAPv2) Success!\n"); success = (struct mschapv2_success_request *)dataoffs; bzero((u_char *)&recv[0], 41); memcpy((u_char *)&recv[0], (u_char *)&success->MsgField[2], 40); CheckAuthenticatorResponse(userdata->password, myvars->NtResponse, myvars->PeerChallenge, myvars->AuthenticatorChallenge, username, (u_char *)&recv[0], &respOk); if (respOk == 1) { debug_printf(DEBUG_AUTHTYPES, "Server authentication check success! Sending phase 2 success!\n"); outframe[0] = MS_CHAPV2_SUCCESS; // We were successful, so generate keying material. NtPasswordHash(userdata->password, (u_char *)&NtHash); HashNtPasswordHash((u_char *)&NtHash, (u_char *)&NtHashHash); GetMasterKey((u_char *)&NtHashHash, myvars->NtResponse, (u_char *)&MasterKey); // Now, get the send key. GetAsymetricStartKey((u_char *)&MasterKey, (u_char *)&mppeSend, 16, TRUE, FALSE); // And the recv key. GetAsymetricStartKey((u_char *)&MasterKey, (u_char *)&mppeRecv, 16, FALSE, FALSE); // Finally, populate our myvars->keyingMaterial. if (myvars->keyingMaterial != NULL) { free(myvars->keyingMaterial); myvars->keyingMaterial = NULL; } myvars->keyingMaterial = (u_char *)malloc(64); // 32 bytes each. if (myvars->keyingMaterial == NULL) return XEMALLOC; bzero(myvars->keyingMaterial, 64); memcpy(&myvars->keyingMaterial[32], &mppeRecv, 16); memcpy(myvars->keyingMaterial, &mppeSend, 16); } else { debug_printf(DEBUG_AUTHTYPES, "Server verification check failed! Sending PHASE 2 FAILURE!\n"); outframe[0] = MS_CHAPV2_FAILURE; } *outsize = 1; break; case MS_CHAPV2_FAILURE: debug_printf(DEBUG_NORMAL, "MS-CHAPv2 Authentication Failure!\n"); *outsize = 0; // We should probably process the failure info, and respond as needed, // but, we really don't care if a failure is retryable, as 802.1x will // just try again anyway. ;) break; case MS_CHAPV2_CHANGE_PWD: debug_printf(DEBUG_NORMAL, "Password changing is not supported!\n"); break; } return XENONE;}int eapmschapv2_get_keys(struct interface_data *thisint){ struct mschapv2_vars *myconf; if ((!thisint) || (!thisint->userdata) || (!thisint->userdata->activemethod) || (!thisint->userdata->activemethod->eap_data)) return XEMALLOC; myconf = (struct mschapv2_vars *)thisint->userdata->activemethod->eap_data; if (thisint->keyingMaterial != NULL) { free(thisint->keyingMaterial); } thisint->keyingMaterial = (char *)malloc(64); if (thisint->keyingMaterial == NULL) return -1; memcpy(thisint->keyingMaterial, myconf->keyingMaterial, 64); thisint->keyingLength = 32; return XENONE;}int eapmschapv2_failed(struct generic_eap_data *thisint){ struct config_eap_mschapv2 *userdata; if ((!thisint) || (!thisint->eap_conf_data)) { debug_printf(DEBUG_AUTHTYPES, "No EAP MS-CHAPv2 configuration data! Nothing to do!\n"); return XEMALLOC; } userdata = (struct config_eap_mschapv2 *)thisint->eap_conf_data;#ifndef NO_PWD_RESET /* if (userdata->password != NULL) { free(userdata->password); userdata->password = NULL; } */#endif return XENONE;}int eapmschapv2_cleanup(struct generic_eap_data *thisint){ struct mschapv2_vars *myvars; if (!thisint) { debug_printf(DEBUG_NORMAL, "Invalid interface structure in eapmschapv2_cleanup()!\n"); return XEMALLOC; } myvars = (struct mschapv2_vars *)thisint->eap_data; if (thisint->eap_data != NULL) { if (myvars->AuthenticatorChallenge != NULL) { free(myvars->AuthenticatorChallenge); myvars->AuthenticatorChallenge = NULL; } if (myvars->PeerChallenge != NULL) { free(myvars->PeerChallenge); myvars->PeerChallenge = NULL; } if (myvars->NtResponse != NULL) { free(myvars->NtResponse); myvars->NtResponse = NULL; } if (myvars->keyingMaterial != NULL) { free(myvars->keyingMaterial); myvars->keyingMaterial = NULL; } free(thisint->eap_data); thisint->eap_data = NULL; } return XENONE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -