📄 eapmschapv2.c
字号:
myvars->NtResponse = (uint8_t *)Malloc(24);
if (myvars->NtResponse == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for the "
"NtResponse!\n");
ipc_events_malloc_failed(NULL);
return EAP_FAIL;
}
eapmschapv2_strip_backslash(eapdata->ident, &username);
if (eapconf->nthash)
{
GenerateNTResponse((char *)myvars->AuthenticatorChallenge,
(char *)myvars->PeerChallenge, username,
eapconf->nthash, (char *)myvars->NtResponse, 1);
} else {
GenerateNTResponse((char *)myvars->AuthenticatorChallenge,
(char *)myvars->PeerChallenge, username,
myvars->password, (char *)myvars->NtResponse, 0);
}
debug_printf(DEBUG_AUTHTYPES, "myvars->NtResponse = ");
debug_hex_printf(DEBUG_AUTHTYPES, (uint8_t *) myvars->NtResponse, 24);
// Everything is good, so continue.
return MAY_CONT;
}
/******************************************************************
*
* Process a success message. It should return one of the eapMethod state
* values.
*
******************************************************************/
uint8_t eapmschapv2_success(eap_type_data *eapdata)
{
struct mschapv2_success_request *success;
int respOk = 0;
struct config_eap_mschapv2 *eapconf;
struct mschapv2_vars *myvars;
uint8_t NtHash[16], NtHashHash[16], MasterKey[16];
uint8_t mppeSend[16], mppeRecv[16];
uint16_t eaplen=0;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return EAP_FAIL;
if (!xsup_assert((eapdata->eapReqData != NULL),
"eapdata->eapReqData != NULL", FALSE))
return EAP_FAIL;
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
FALSE))
return EAP_FAIL;
if (!xsup_assert((eapdata->eap_conf_data != NULL),
"eapdata->eap_conf_data != NULL", FALSE))
return EAP_FAIL;
eapconf = (struct config_eap_mschapv2 *)eapdata->eap_conf_data;
myvars = (struct mschapv2_vars *)eapdata->eap_data;
success = (struct mschapv2_success_request *)&eapdata->eapReqData[sizeof(struct eap_header)];
eaplen = eap_type_common_get_eap_length(eapdata->eapReqData);
// Add a NULL to the end, in case we didn't get one.
eapdata->eapReqData[eaplen+1] = 0x00;
if (eapconf->nthash)
{
CheckAuthenticatorResponse(eapconf->nthash,
(char *)myvars->NtResponse,
(char *)myvars->PeerChallenge,
(char *)myvars->AuthenticatorChallenge,
eapdata->ident,
(char *)&success->MsgField[2], &respOk, 1);
} else {
CheckAuthenticatorResponse(myvars->password,
(char *)myvars->NtResponse,
(char *)myvars->PeerChallenge,
(char *)myvars->AuthenticatorChallenge,
eapdata->ident,
(char *)&success->MsgField[2], &respOk, 0);
}
if (respOk != 1)
{
debug_printf(DEBUG_NORMAL, "Authenticator response invalid!\n");
return EAP_FAIL;
}
// Otherwise, generate our keying material.
// We were successful, so generate keying material.
if (!eapconf->nthash)
{
NtPasswordHash(myvars->password, (char *)&NtHash);
}
else
{
process_hex(myvars->password, strlen(myvars->password),
(char *)NtHash);
}
HashNtPasswordHash((char *)&NtHash, (char *)&NtHashHash);
GetMasterKey((char *)&NtHashHash, (char *)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.
FREE(myvars->keyingMaterial);
myvars->keyingMaterial = (uint8_t *)Malloc(64); // 32 bytes each.
if (myvars->keyingMaterial == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store keying"
" material!\n");
ipc_events_malloc_failed(NULL);
return EAP_FAIL;
}
memcpy(&myvars->keyingMaterial[32], &mppeRecv, 16);
memcpy(myvars->keyingMaterial, &mppeSend, 16);
eapdata->decision = COND_SUCC;
eapdata->eapKeyAvailable = TRUE;
eapdata->altAccept = TRUE;
return MAY_CONT;
}
/******************************************************************
*
* Parse an MS-CHAPv2 error string in to the numeric failure value,
* and the text error value.
*
******************************************************************/
uint8_t eapmschapv2_parse_error_string(char *err_string, uint16_t *errcode,
char **errtext)
{
/*
The Message field format is:
"E=eeeeeeeeee R=r C=cccccccccccccccccccccccccccccccc V=vvvvvvvvvv M=<msg>"
*/
uint16_t offset = 0;
char *strdata = NULL;
if ((err_string[0] != 'E') || (err_string[1] != '='))
{
debug_printf(DEBUG_NORMAL, "Message string contains invalid starting "
"characters. It should start with 'E=', but actually "
"started with '%c%c'.\n", err_string[0], err_string[1]);
return XEGENERROR;
}
strdata = err_string + 2; // Start beyond the E= portion.
while ((offset < strlen(err_string)) && (strdata[offset] != ' '))
{
offset++;
}
if (strdata[offset] == ' ')
{
strdata[offset] = 0x00; // Set a NULL so that atoi can handle it.
*errcode = atoi(strdata);
debug_printf(DEBUG_AUTHTYPES, "Numeric error code is %d\n", *errcode);
}
offset++;
if ((strdata[offset] != 'R') || (strdata[offset+1] != '='))
{
debug_printf(DEBUG_NORMAL, "Message contains invalid characters for "
"second element. It should be 'R=', but actually was "
"'%c%c'.\n", strdata[offset], strdata[offset+1]);
return XEGENERROR;
}
offset+=4; // This should get us to the C= section.
if ((strdata[offset] != 'C') || (strdata[offset+1] != '='))
{
debug_printf(DEBUG_NORMAL, "Message contains invalid characters for "
"third element. It should be 'C=', but actually was "
"'%c%c'.\n", strdata[offset], strdata[offset+1]);
return XEGENERROR;
}
offset+=35; // This should get us to the V= section.
if ((strdata[offset] != 'V') || (strdata[offset+1] != '='))
{
debug_printf(DEBUG_NORMAL, "Message contains invalid characters for "
"fourth element. It should be 'V=', but actually was "
"'%c%c'.\n", strdata[offset], strdata[offset+1]);
return XEGENERROR;
}
offset+=2;
strdata += offset;
offset = 0;
while ((offset < strlen(strdata)) && (strdata[offset] != ' '))
{
offset++;
}
if (strdata[offset] != ' ')
{
debug_printf(DEBUG_AUTHTYPES, "Message didn't appear to be valid following"
" the password change section. (Section 'V=')\n");
// Some authentication servers don't send a properly formatted failure
// response. They may omit the text version of the error code.
return XENONE;
}
// Otherwise, set this to a null character.
strdata[offset] = 0x00;
if (atoi(strdata) != MSCHAPV2_PASSWORD_CHANGE_VER)
{
debug_printf(DEBUG_NORMAL, "The server requested a password change "
"protocol version that we don't understand. Expected "
"version %d. Got version %d.\n",
MSCHAPV2_PASSWORD_CHANGE_VER, atoi(strdata));
// This error isn't fatal!
}
// Finally! We get to the text version of the failure.
offset++;
strdata += offset;
offset = 0;
if ((strdata[offset] != 'M') || (strdata[offset+1] != '='))
{
debug_printf(DEBUG_NORMAL, "This message didn't appear to have a valid"
" text version of the error! Expected 'M=', found "
"'%c%c'.\n", strdata[offset], strdata[offset+1]);
return XEGENERROR;
}
// Otherwise, update our pointer to point to the text of the error.
strdata += 2;
*errtext = strdata;
return XENONE;
}
/******************************************************************
*
* Process a failure message.
*
******************************************************************/
uint8_t eapmschapv2_failure(eap_type_data *eapdata)
{
struct mschapv2_fail_request *fail = NULL;
char *err_string = NULL, *err_text = NULL;
uint16_t errlen = 0, errcode = 0;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return EAP_FAIL;
if (!xsup_assert((eapdata->eapReqData != NULL),
"eapdata->eapReqData != NULL", FALSE))
return EAP_FAIL;
// In case we fail parsing the error code, we still end up with the
// proper end result.
eapdata->altReject = TRUE;
fail = (struct mschapv2_fail_request *)&eapdata->eapReqData[sizeof(struct eap_header)];
if (fail->OpCode != MS_CHAPV2_FAILURE)
{
debug_printf(DEBUG_NORMAL, "The OpCode in the MS-CHAPv2 packet doesn't "
"indicate that we got an error. But, we ended up in the "
"error state anyway?\n");
return EAP_FAIL;
}
errlen = ntohs(fail->MS_Length);
err_string = Malloc(errlen+1);
if (err_string == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory needed to parse "
"the error string!\n");
ipc_events_malloc_failed(NULL);
return EAP_FAIL;
}
memcpy(err_string, fail->MsgField, errlen);
debug_printf(DEBUG_AUTHTYPES, "Error string is : %s\n", err_string);
if (eapmschapv2_parse_error_string(err_string, &errcode, &err_text) != XENONE)
{
return EAP_FAIL;
}
switch (errcode)
{
case MSCHAPV2_RESTRICTED_LOGON_HOURS:
debug_printf(DEBUG_NORMAL, "Your account is restricted to the hours "
"you may log in.\n");
ipc_events_error(NULL, IPC_EVENT_ERROR_RESTRICTED_HOURS, NULL);
break;
case MSCHAPV2_ACCT_DISABLED:
debug_printf(DEBUG_NORMAL, "Your account has been disabled.\n");
ipc_events_error(NULL, IPC_EVENT_ERROR_ACCT_DISABLED, NULL);
break;
case MSCHAPV2_PASSWD_EXPIRED:
debug_printf(DEBUG_NORMAL, "Your password has expired.\n");
ipc_events_error(NULL, IPC_EVENT_ERROR_PASSWD_EXPIRED, NULL);
break;
case MSCHAPV2_NO_DIALIN_PERMISSION:
debug_printf(DEBUG_NORMAL, "Your account does not have permission to "
"use this network.\n");
ipc_events_error(NULL, IPC_EVENT_ERROR_NO_PERMS, NULL);
break;
case MSCHAPV2_AUTHENTICATION_FAILURE:
debug_printf(DEBUG_NORMAL, "General authentication failure.\n");
// Don't send an error event here, because it won't be useful to the user.
// Instead, they should look at the log file to determine what went wrong.
break;
case MSCHAPV2_CHANGING_PASSWORD:
debug_printf(DEBUG_NORMAL, "There was an error changing your password."
"\n");
ipc_events_error(NULL, IPC_EVENT_ERROR_CHANGING_PASSWD, NULL);
break;
default:
debug_printf(DEBUG_NORMAL, "Unknown error type %d returned. Please "
"see text description of the error (on the next line) "
"for more information.\n");
ipc_events_error(NULL, IPC_EVENT_ERROR_TEXT, err_text);
break;
}
debug_printf(DEBUG_NORMAL, "Server provided text description of the error : "
"%s\n", err_text);
return EAP_FAIL;
}
/******************************************************************
*
* Process an EAP-MSCHAPv2 packet, and develop the data needed for
* the response.
*
******************************************************************/
void eapmschapv2_process(eap_type_data *eapdata)
{
struct config_eap_mschapv2 *eapconf = NULL;
struct mschapv2_challenge *challenge = NULL;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return;
if (!xsup_assert((eapdata->eap_conf_data != NULL),
"eapdata->eap_conf_data != NULL", FALSE))
return;
if (!xsup_assert((eapdata->eapReqData != NULL),
"eapdata->eapReqData != NULL", FALSE))
return;
eapconf = (struct config_eap_mschapv2 *)eapdata->eap_conf_data;
if (eapdata->methodState == INIT)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -