📄 eapmschapv2.c
字号:
/******************************************************************* * EAP-MSCHAPv2 Function implementations * * Licensed under a dual GPL/BSD license. (See LICENSE file for more info.) * * File: eapmschapv2.c * * Authors: Chris.Hessing@utah.edu * * $Id: eapmschapv2.c,v 1.35 2006/06/01 22:49:50 galimorerpg Exp $ * $Date: 2006/06/01 22:49:50 $ * $Log: eapmschapv2.c,v $ * Revision 1.35 2006/06/01 22:49:50 galimorerpg * Converted all instances of u_char to uint8_t * Fixed a bad #include in the generic frame handler. * * Revision 1.34 2006/05/29 04:17:58 chessing * Fixes for some memory leaks. * * Revision 1.33 2006/04/25 01:17:43 chessing * LOTS of code cleanups, new error checking/debugging code added, and other misc. fixes/changes. * * Revision 1.32 2006/01/03 04:02:35 chessing * Added the ability to store the PEAP password in a hashed format. (Basically, an MS-CHAPv1 hash.) Also added an 'ntpwdhash' program to the tools directory that will convert a cleartext password in to a hash that can be copied to the configuration file. * * Revision 1.31 2005/10/17 03:56:54 chessing * Updates to the libxsupconfig library. It no longer relies on other source from the main tree, so it can be used safely in other code with problems. * * Revision 1.30 2005/10/14 02:26:18 shaftoe * - cleanup gcc 4 warnings * - (re)add support for a pid in the form of /var/run/xsupplicant.<iface>.pid * * -- Eric Evans <eevans@sym-link.com> * * Revision 1.29 2005/08/09 01:39:16 chessing * Cleaned out old commit notes from the released version. Added a few small features including the ability to disable the friendly warnings that are spit out. (Such as the warning that is displayed when keys aren't rotated after 10 minutes.) We should also be able to start when the interface is down. Last, but not least, we can handle empty network configs. (This may be useful for situations where there isn't a good reason to have a default network defined.) * * *******************************************************************/#include <openssl/rand.h>#include <string.h>#include <netinet/in.h>#include "profile.h"#include "xsupconfig.h"#include "xsup_debug.h"#include "xsup_err.h"#include "frame_structs.h"#include "eapmschapv2.h"#include "mschapv2.h"#include "eap.h"#ifdef USE_EFENCE#include <efence.h>#endifint eapmschapv2_setup(struct generic_eap_data *thisint){ struct mschapv2_vars *myvars; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; thisint->eap_data = (uint8_t *)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, uint8_t *dataoffs, int insize, uint8_t *outframe, int *outsize){ struct mschapv2_challenge *challenge; struct mschapv2_response *response; struct mschapv2_success_request *success; struct mschapv2_vars *myvars; char *username; int respOk; uint8_t recv[41]; uint8_t NtHash[16], NtHashHash[16], MasterKey[16]; uint8_t mppeSend[16], mppeRecv[16]; struct config_eap_mschapv2 *userdata; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((dataoffs != NULL), "dataoffs != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((outframe != NULL), "outframe != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((outsize != NULL), "outsize != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((thisint->eap_conf_data != NULL), "thisint->eap_conf_data != NULL", FALSE)) return XEMALLOC; userdata = (struct config_eap_mschapv2 *)thisint->eap_conf_data; if (!xsup_assert((thisint->eap_data != NULL), "thisint->eap_data != NULL", FALSE)) return XEMALLOC; myvars = (struct mschapv2_vars *)thisint->eap_data; if ((thisint->tempPwd == NULL) && (userdata->password == NULL) && (userdata->nthash == 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 = (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, (uint8_t *) myvars->AuthenticatorChallenge, 16); if (myvars->PeerChallenge != NULL) { free(myvars->PeerChallenge); myvars->PeerChallenge = NULL; } // Ignore the RADIUS host, we probably don't care. myvars->PeerChallenge = (char *)malloc(16); if (myvars->PeerChallenge == NULL) return XEMALLOC; RAND_bytes((uint8_t *) myvars->PeerChallenge, 16); debug_printf(DEBUG_AUTHTYPES, "Generated PeerChallenge : "); debug_hex_printf(DEBUG_AUTHTYPES, (uint8_t *) myvars->PeerChallenge,16); if (myvars->NtResponse != NULL) { free(myvars->NtResponse); myvars->NtResponse = NULL; } myvars->NtResponse = (char *)malloc(24); if (myvars->NtResponse == NULL) return XEMALLOC; if (userdata->nthash) { GenerateNTResponse(myvars->AuthenticatorChallenge, myvars->PeerChallenge, username, userdata->nthash, myvars->NtResponse, 1); } else { GenerateNTResponse(myvars->AuthenticatorChallenge, myvars->PeerChallenge, username, userdata->password, myvars->NtResponse, 0); } debug_printf(DEBUG_AUTHTYPES, "myvars->NtResponse = "); debug_hex_printf(DEBUG_AUTHTYPES, (uint8_t *) 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((uint8_t *)&response->Peer_Challenge, myvars->PeerChallenge, 16); bzero((uint8_t *)&response->Reserved, 8); memcpy((uint8_t *)&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((uint8_t *)&recv[0], 41); memcpy((uint8_t *)&recv[0], (uint8_t *)&success->MsgField[2], 40); if (userdata->nthash) { CheckAuthenticatorResponse(userdata->nthash, myvars->NtResponse, myvars->PeerChallenge, myvars->AuthenticatorChallenge, username, (char *)&recv[0], &respOk, 1); } else { CheckAuthenticatorResponse(userdata->password, myvars->NtResponse, myvars->PeerChallenge, myvars->AuthenticatorChallenge, username, (char *)&recv[0], &respOk, 0); } 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, (char *)&NtHash); HashNtPasswordHash((char *)&NtHash, (char *)&NtHashHash); GetMasterKey((char *)&NtHashHash, myvars->NtResponse, (char *)&MasterKey); // Now, get the send key. GetAsymetricStartKey((char *)&MasterKey, (char *)&mppeSend, 16, TRUE, FALSE); // And the recv key. GetAsymetricStartKey((char *)&MasterKey, (char *)&mppeRecv, 16, FALSE, FALSE); // Finally, populate our myvars->keyingMaterial. if (myvars->keyingMaterial != NULL) { free(myvars->keyingMaterial); myvars->keyingMaterial = NULL; } myvars->keyingMaterial = (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; 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; struct config_network *network_data; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; network_data = config_get_network_config(); if (!xsup_assert((network_data != NULL), "network_data != NULL", FALSE)) return XEMALLOC; myconf = (struct mschapv2_vars *)network_data->activemethod->eap_data; if (thisint->keyingMaterial != NULL) { free(thisint->keyingMaterial); } thisint->keyingMaterial = (uint8_t *)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 (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((thisint->eap_conf_data != NULL), "thisint->eap_conf_data != NULL", FALSE)) 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 (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) 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 + -