method_eapmsg: Let inner method handle EAP-Identity packets
With EapHost inner method, this is a must. Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
b2edd74270
commit
1290d83b9d
@ -131,10 +131,9 @@ namespace eap
|
|||||||
/// Constructs a method
|
/// Constructs a method
|
||||||
///
|
///
|
||||||
/// \param[in] mod Module to use for global services
|
/// \param[in] mod Module to use for global services
|
||||||
/// \param[in] identity User identity
|
|
||||||
/// \param[in] inner Inner method
|
/// \param[in] inner Inner method
|
||||||
///
|
///
|
||||||
method_eapmsg(_In_ module &mod, _In_ const wchar_t *identity, _In_ method *inner);
|
method_eapmsg(_In_ module &mod, _In_ method *inner);
|
||||||
|
|
||||||
/// \name Session management
|
/// \name Session management
|
||||||
/// @{
|
/// @{
|
||||||
@ -161,8 +160,6 @@ namespace eap
|
|||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::wstring m_identity; ///< User identity
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Communication phase
|
/// Communication phase
|
||||||
///
|
///
|
||||||
|
@ -163,8 +163,7 @@ void eap::method_defrag::get_response_packet(
|
|||||||
// eap::method_eapmsg
|
// eap::method_eapmsg
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
eap::method_eapmsg::method_eapmsg(_In_ module &mod, _In_ const wchar_t *identity, _In_ method *inner) :
|
eap::method_eapmsg::method_eapmsg(_In_ module &mod, _In_ method *inner) :
|
||||||
m_identity(identity),
|
|
||||||
m_phase(phase_t::unknown),
|
m_phase(phase_t::unknown),
|
||||||
method_tunnel(mod, inner)
|
method_tunnel(mod, inner)
|
||||||
{
|
{
|
||||||
@ -196,27 +195,17 @@ EapPeerMethodResponseAction eap::method_eapmsg::process_request_packet(
|
|||||||
_In_ DWORD dwReceivedPacketSize)
|
_In_ DWORD dwReceivedPacketSize)
|
||||||
{
|
{
|
||||||
switch (m_phase) {
|
switch (m_phase) {
|
||||||
case phase_t::identity: {
|
case phase_t::identity:
|
||||||
// Convert identity to UTF-8.
|
|
||||||
sanitizing_string identity_utf8;
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0, m_identity, identity_utf8, NULL, NULL);
|
|
||||||
|
|
||||||
// Build EAP-Response/Identity packet.
|
// Build EAP-Response/Identity packet.
|
||||||
auto size_identity = identity_utf8.length(), size_packet = size_identity + sizeof(EapPacket);
|
EapPacket hdr_req;
|
||||||
assert(size_packet <= MAXWORD); // Packets spanning over 64kB are not supported.
|
hdr_req.Code = EapCodeRequest;
|
||||||
eap_packet pck;
|
hdr_req.Id = 0;
|
||||||
if (!pck.create(EapCodeResponse, 0, (WORD)size_packet))
|
*reinterpret_cast<unsigned short*>(hdr_req.Length) = htons(sizeof(EapPacket));
|
||||||
throw win_runtime_error(__FUNCTION__ " EapPacket creation failed.");
|
hdr_req.Data[0] = (BYTE)eap_type_t::identity;
|
||||||
pck->Data[0] = (BYTE)eap_type_t::identity;
|
|
||||||
memcpy(pck->Data + 1, identity_utf8.data(), size_identity);
|
|
||||||
|
|
||||||
// Diameter AVP (EAP-Message=79)
|
|
||||||
m_packet_res.clear();
|
|
||||||
diameter_avp_append(79, diameter_avp_flag_mandatory, (const EapPacket*)pck, (unsigned int)size_packet, m_packet_res);
|
|
||||||
|
|
||||||
m_phase = phase_t::finished;
|
m_phase = phase_t::finished;
|
||||||
return EapPeerMethodResponseActionSend;
|
m_packet_res.clear();
|
||||||
}
|
return method_tunnel::process_request_packet(&hdr_req, sizeof(EapPacket));
|
||||||
|
|
||||||
case phase_t::finished: {
|
case phase_t::finished: {
|
||||||
EapPeerMethodResponseAction action = EapPeerMethodResponseActionNone;
|
EapPeerMethodResponseAction action = EapPeerMethodResponseActionNone;
|
||||||
@ -271,16 +260,15 @@ void eap::method_eapmsg::get_response_packet(
|
|||||||
_In_opt_ DWORD size_max)
|
_In_opt_ DWORD size_max)
|
||||||
{
|
{
|
||||||
if (m_packet_res.empty()) {
|
if (m_packet_res.empty()) {
|
||||||
assert(size_max >= sizeof(diameter_avp_header)); // We should be able to respond with at least Diameter AVP header.
|
|
||||||
|
|
||||||
if (size_max > 0xffffff) size_max = 0xffffff; // Diameter AVP maximum size is 16MB.
|
if (size_max > 0xffffff) size_max = 0xffffff; // Diameter AVP maximum size is 16MB.
|
||||||
|
|
||||||
// Get data from underlying method.
|
// Get data from underlying method.
|
||||||
|
assert(size_max >= sizeof(diameter_avp_header)); // We should be able to respond with at least Diameter AVP header.
|
||||||
method_tunnel::get_response_packet(packet, size_max - sizeof(diameter_avp_header));
|
method_tunnel::get_response_packet(packet, size_max - sizeof(diameter_avp_header));
|
||||||
|
|
||||||
// Prepare EAP-Message Diameter AVP header.
|
// Prepare EAP-Message Diameter AVP header.
|
||||||
diameter_avp_header hdr;
|
diameter_avp_header hdr;
|
||||||
*reinterpret_cast<unsigned int*>(hdr.code) = htonl(79);
|
*reinterpret_cast<unsigned int*>(hdr.code) = htonl(79); // EAP-Message=79
|
||||||
hdr.flags = diameter_avp_flag_mandatory;
|
hdr.flags = diameter_avp_flag_mandatory;
|
||||||
size_t size_packet = packet.size() + sizeof(diameter_avp_header);
|
size_t size_packet = packet.size() + sizeof(diameter_avp_header);
|
||||||
assert(size_packet <= 0xffffff); // Packets spanning over 16MB are not supported.
|
assert(size_packet <= 0xffffff); // Packets spanning over 16MB are not supported.
|
||||||
@ -292,10 +280,12 @@ void eap::method_eapmsg::get_response_packet(
|
|||||||
// Add padding.
|
// Add padding.
|
||||||
packet.insert(packet.end(), (unsigned int)((4 - size_packet) % 4), 0);
|
packet.insert(packet.end(), (unsigned int)((4 - size_packet) % 4), 0);
|
||||||
} else {
|
} else {
|
||||||
if (m_packet_res.size() > size_max)
|
// We have a response packet ready.
|
||||||
throw invalid_argument(string_printf(__FUNCTION__ " This method does not support packet fragmentation, but the data size is too big to fit in one packet (packet: %zu, maximum: %u).", m_packet_res.size(), size_max));
|
size_t size_packet = m_packet_res.size();
|
||||||
|
if (size_packet > size_max)
|
||||||
|
throw invalid_argument(string_printf(__FUNCTION__ " This method does not support packet fragmentation, but the data size is too big to fit in one packet (packet: %zu, maximum: %u).", size_packet, size_max));
|
||||||
|
|
||||||
packet.assign(m_packet_res.begin(), m_packet_res.end());
|
packet.assign(m_packet_res.cbegin(), m_packet_res.cend());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,14 +690,14 @@ eap::method* eap::peer_ttls::make_method(_In_ config_method_tls_tunnel &cfg, _In
|
|||||||
|
|
||||||
case eap_type_t::mschapv2:
|
case eap_type_t::mschapv2:
|
||||||
meth_inner.reset(
|
meth_inner.reset(
|
||||||
new method_eapmsg (*this, cred_inner->get_identity().c_str(),
|
new method_eapmsg (*this,
|
||||||
new method_eap (*this, eap_type_t::mschapv2, *cred_inner,
|
new method_eap (*this, eap_type_t::mschapv2, *cred_inner,
|
||||||
new method_mschapv2(*this, dynamic_cast<config_method_mschapv2&>(*cfg_inner), dynamic_cast<credentials_pass&>(*cred_inner)))));
|
new method_mschapv2(*this, dynamic_cast<config_method_mschapv2&>(*cfg_inner), dynamic_cast<credentials_pass&>(*cred_inner)))));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eap_type_t::gtc:
|
case eap_type_t::gtc:
|
||||||
meth_inner.reset(
|
meth_inner.reset(
|
||||||
new method_eapmsg(*this, cred_inner->get_identity().c_str(),
|
new method_eapmsg(*this,
|
||||||
new method_eap (*this, eap_type_t::gtc, *cred_inner,
|
new method_eap (*this, eap_type_t::gtc, *cred_inner,
|
||||||
new method_gtc (*this, dynamic_cast<config_method_eapgtc&>(*cfg_inner), dynamic_cast<credentials&>(*cred_inner)))));
|
new method_gtc (*this, dynamic_cast<config_method_eapgtc&>(*cfg_inner), dynamic_cast<credentials&>(*cred_inner)))));
|
||||||
break;
|
break;
|
||||||
@ -705,7 +705,7 @@ eap::method* eap::peer_ttls::make_method(_In_ config_method_tls_tunnel &cfg, _In
|
|||||||
#if EAP_INNER_EAPHOST
|
#if EAP_INNER_EAPHOST
|
||||||
case eap_type_t::undefined:
|
case eap_type_t::undefined:
|
||||||
meth_inner.reset(
|
meth_inner.reset(
|
||||||
new method_eapmsg (*this, cred_inner->get_identity().c_str(),
|
new method_eapmsg (*this,
|
||||||
new method_eaphost(*this, dynamic_cast<config_method_eaphost&>(*cfg_inner), dynamic_cast<credentials_eaphost&>(*cred_inner))));
|
new method_eaphost(*this, dynamic_cast<config_method_eaphost&>(*cfg_inner), dynamic_cast<credentials_eaphost&>(*cred_inner))));
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user