256 lines
8.9 KiB
C++
256 lines
8.9 KiB
C++
/*
|
|
SPDX-License-Identifier: GPL-3.0-or-later
|
|
Copyright © 2015-2022 Amebis
|
|
Copyright © 2016 GÉANT
|
|
*/
|
|
|
|
#include "PCH.h"
|
|
|
|
using namespace std;
|
|
using namespace winstd;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// eap::method_eaphost
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
eap::method_eaphost::method_eaphost(_In_ module &mod, _In_ config_method_eaphost &cfg, _In_ credentials_eaphost &cred) :
|
|
m_cfg(cfg),
|
|
m_cred(cred),
|
|
m_session_id(0),
|
|
method(mod)
|
|
{
|
|
}
|
|
|
|
|
|
void eap::method_eaphost::begin_session(
|
|
_In_ DWORD dwFlags,
|
|
_In_ const EapAttributes *pAttributeArray,
|
|
_In_ HANDLE hTokenImpersonateUser,
|
|
_In_opt_ DWORD dwMaxSendPacketSize)
|
|
{
|
|
method::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize);
|
|
|
|
// Presume authentication will fail with generic protocol failure. (Pesimist!!!)
|
|
// We will reset once we get get_result(Success) call.
|
|
m_cfg.m_last_status = config_method::status_t::auth_failed;
|
|
m_cfg.m_last_msg.clear();
|
|
|
|
// Create EapHost peer session using available connection data (m_cfg) and user data (m_cred).
|
|
eap_error_runtime error;
|
|
DWORD dwResult = EapHostPeerBeginSession(
|
|
dwFlags,
|
|
m_cfg.get_type(),
|
|
pAttributeArray,
|
|
hTokenImpersonateUser,
|
|
(DWORD)m_cfg.m_cfg_blob.size(),
|
|
m_cfg.m_cfg_blob.data(),
|
|
(DWORD)m_cred.m_cred_blob.size(),
|
|
m_cred.m_cred_blob.data(),
|
|
dwMaxSendPacketSize,
|
|
NULL, NULL, NULL,
|
|
&m_session_id,
|
|
get_ptr(error));
|
|
if (dwResult == ERROR_SUCCESS) {
|
|
// Session succesfully created.
|
|
} else if (error)
|
|
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerBeginSession failed.");
|
|
else
|
|
throw win_runtime_error(dwResult, __FUNCTION__ " EapHostPeerBeginSession failed.");
|
|
}
|
|
|
|
|
|
void eap::method_eaphost::end_session()
|
|
{
|
|
// End EapHost peer session.
|
|
eap_error_runtime error;
|
|
DWORD dwResult = EapHostPeerEndSession(m_session_id, get_ptr(error));
|
|
if (dwResult == ERROR_SUCCESS) {
|
|
// Session successfuly ended.
|
|
} else if (error)
|
|
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerEndSession failed.");
|
|
else
|
|
throw win_runtime_error(dwResult, __FUNCTION__ " EapHostPeerEndSession failed.");
|
|
|
|
method::end_session();
|
|
}
|
|
|
|
|
|
EapPeerMethodResponseAction eap::method_eaphost::process_request_packet(
|
|
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
|
|
_In_ DWORD dwReceivedPacketSize)
|
|
{
|
|
assert(pReceivedPacket || dwReceivedPacketSize == 0);
|
|
|
|
// Let EapHost peer process the packet.
|
|
EapHostPeerResponseAction action;
|
|
eap_error_runtime error;
|
|
DWORD dwResult = EapHostPeerProcessReceivedPacket(
|
|
m_session_id,
|
|
dwReceivedPacketSize,
|
|
reinterpret_cast<const BYTE*>(pReceivedPacket),
|
|
&action,
|
|
get_ptr(error));
|
|
if (dwResult == ERROR_SUCCESS) {
|
|
// Packet successfuly processed.
|
|
return action_h2p(action);
|
|
} else if (error)
|
|
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerProcessReceivedPacket failed.");
|
|
else
|
|
throw win_runtime_error(dwResult, __FUNCTION__ " EapHostPeerProcessReceivedPacket failed.");
|
|
}
|
|
|
|
|
|
void eap::method_eaphost::get_response_packet(
|
|
_Out_ sanitizing_blob &packet,
|
|
_In_opt_ DWORD size_max)
|
|
{
|
|
// Let EapHost peer prepare response packet.
|
|
LPBYTE _packet;
|
|
eap_error_runtime error;
|
|
DWORD dwResult = EapHostPeerGetSendPacket(
|
|
m_session_id,
|
|
&size_max,
|
|
&_packet,
|
|
get_ptr(error));
|
|
if (dwResult == ERROR_SUCCESS) {
|
|
// Packet successfuly prepared.
|
|
packet.assign(_packet, _packet + size_max);
|
|
} else if (error)
|
|
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerGetSendPacket failed.");
|
|
else
|
|
throw win_runtime_error(dwResult, __FUNCTION__ " EapHostPeerGetSendPacket failed.");
|
|
}
|
|
|
|
|
|
void eap::method_eaphost::get_result(
|
|
_In_ EapPeerMethodResultReason reason,
|
|
_Inout_ EapPeerMethodResult *pResult)
|
|
{
|
|
// Let EapHost peer return result.
|
|
eap_error_runtime error;
|
|
EapHostPeerMethodResult result = {};
|
|
DWORD dwResult = EapHostPeerGetResult(
|
|
m_session_id,
|
|
EapHostPeerMethodResultFromMethod,
|
|
&result,
|
|
get_ptr(error));
|
|
if (dwResult == ERROR_SUCCESS) {
|
|
// Result successfuly returned.
|
|
method::get_result(reason, pResult);
|
|
|
|
pResult->dwFailureReasonCode = result.dwFailureReasonCode;
|
|
pResult->pAttribArray = result.pAttribArray;
|
|
|
|
if (result.pEapError) {
|
|
// Transfer error to our module memory space.
|
|
pResult->pEapError = m_module.make_error(result.pEapError);
|
|
EapHostPeerFreeEapError(result.pEapError);
|
|
result.pEapError = NULL;
|
|
}
|
|
|
|
if (result.fSaveConnectionData) {
|
|
// Update configuration BLOB.
|
|
m_cfg.m_cfg_blob.assign(result.pConnectionData, result.pConnectionData + result.dwSizeofConnectionData);
|
|
}
|
|
|
|
if (result.fSaveUserData) {
|
|
// Update credentials BLOB.
|
|
m_cred.m_cred_blob.assign(result.pUserData, result.pUserData + result.dwSizeofUserData);
|
|
}
|
|
|
|
if (reason == EapPeerMethodResultSuccess)
|
|
m_cfg.m_last_status = config_method::status_t::success;
|
|
|
|
// Ask EAP host to save the configuration (connection data).
|
|
pResult->fSaveConnectionData = TRUE;
|
|
} else if (error)
|
|
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerGetResult failed.");
|
|
else
|
|
throw win_runtime_error(dwResult, __FUNCTION__ " EapHostPeerGetResult failed.");
|
|
}
|
|
|
|
|
|
void eap::method_eaphost::get_ui_context(_Out_ sanitizing_blob &context_data)
|
|
{
|
|
// Get EapHost peer UI context data.
|
|
DWORD dwUIContextDataSize;
|
|
LPBYTE pUIContextData;
|
|
eap_error_runtime error;
|
|
DWORD dwResult = EapHostPeerGetUIContext(
|
|
m_session_id,
|
|
&dwUIContextDataSize,
|
|
&pUIContextData,
|
|
get_ptr(error));
|
|
if (dwResult == ERROR_SUCCESS) {
|
|
// UI context data successfuly returned.
|
|
context_data.assign(pUIContextData, pUIContextData + dwUIContextDataSize);
|
|
|
|
// TODO: Test if EapHostPeerGetUIContext() requires us to free the buffer.
|
|
//EapHostPeerFreeMemory(pUIContextData);
|
|
} else if (error)
|
|
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerGetUIContext failed.");
|
|
else
|
|
throw win_runtime_error(dwResult, __FUNCTION__ " EapHostPeerGetUIContext failed.");
|
|
}
|
|
|
|
|
|
EapPeerMethodResponseAction eap::method_eaphost::set_ui_context(
|
|
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
|
|
_In_ DWORD dwUIContextDataSize)
|
|
{
|
|
// Set EapHost peer UI context data.
|
|
EapHostPeerResponseAction action;
|
|
eap_error_runtime error;
|
|
DWORD dwResult = EapHostPeerSetUIContext(
|
|
m_session_id,
|
|
dwUIContextDataSize,
|
|
pUIContextData,
|
|
&action,
|
|
get_ptr(error));
|
|
if (dwResult == ERROR_SUCCESS) {
|
|
// UI context data successfuly returned.
|
|
return action_h2p(action);
|
|
} else if (error)
|
|
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerSetUIContext failed.");
|
|
else
|
|
throw win_runtime_error(dwResult, __FUNCTION__ " EapHostPeerSetUIContext failed.");
|
|
}
|
|
|
|
|
|
void eap::method_eaphost::get_response_attributes(_Out_ EapAttributes *pAttribs)
|
|
{
|
|
// Get response attributes from EapHost peer.
|
|
eap_error_runtime error;
|
|
DWORD dwResult = EapHostPeerGetResponseAttributes(
|
|
m_session_id,
|
|
pAttribs,
|
|
get_ptr(error));
|
|
if (dwResult == ERROR_SUCCESS) {
|
|
// Response attributes successfuly returned.
|
|
} else if (error)
|
|
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerGetResponseAttributes failed.");
|
|
else
|
|
throw win_runtime_error(dwResult, __FUNCTION__ " EapHostPeerGetResponseAttributes failed.");
|
|
}
|
|
|
|
|
|
EapPeerMethodResponseAction eap::method_eaphost::set_response_attributes(_In_ const EapAttributes *pAttribs)
|
|
{
|
|
// Set response attributes for EapHost peer.
|
|
EapHostPeerResponseAction action;
|
|
eap_error_runtime error;
|
|
DWORD dwResult = EapHostPeerSetResponseAttributes(
|
|
m_session_id,
|
|
pAttribs,
|
|
&action,
|
|
get_ptr(error));
|
|
if (dwResult == ERROR_SUCCESS) {
|
|
// Response attributes successfuly set.
|
|
return action_h2p(action);
|
|
} else if (error)
|
|
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerGetResponseAttributes failed.");
|
|
else
|
|
throw win_runtime_error(dwResult, __FUNCTION__ " EapHostPeerGetResponseAttributes failed.");
|
|
}
|