Support for various peer action request extended

This commit is contained in:
Simon Rozman 2016-10-27 10:00:18 +02:00
parent fc008bcfb4
commit 654c965851
13 changed files with 160 additions and 166 deletions

View File

@ -105,10 +105,9 @@ namespace eap
/// ///
/// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
/// ///
virtual void process_request_packet( virtual EapPeerMethodResponseAction process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize, _In_ DWORD dwReceivedPacketSize) = 0;
_Out_ EapPeerMethodOutput *pEapOutput) = 0;
/// ///
/// Obtains a response packet from the EAP method. /// Obtains a response packet from the EAP method.
@ -151,10 +150,9 @@ namespace eap
/// ///
/// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx) /// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx)
/// ///
virtual void set_ui_context( virtual EapPeerMethodResponseAction set_ui_context(
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData, _In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
_In_ DWORD dwUIContextDataSize, _In_ DWORD dwUIContextDataSize);
_Out_ EapPeerMethodOutput *pEapOutput);
/// @} /// @}
@ -173,9 +171,7 @@ namespace eap
/// ///
/// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx) /// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx)
/// ///
virtual void set_response_attributes( virtual EapPeerMethodResponseAction set_response_attributes(_In_ const EapAttributes *pAttribs);
_In_ const EapAttributes *pAttribs,
_Out_ EapPeerMethodOutput *pEapOutput);
/// @} /// @}

View File

@ -122,16 +122,15 @@ void eap::method::get_ui_context(
} }
void eap::method::set_ui_context( EapPeerMethodResponseAction eap::method::set_ui_context(
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData, _In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
_In_ DWORD dwUIContextDataSize, _In_ DWORD dwUIContextDataSize)
_Out_ EapPeerMethodOutput *pEapOutput)
{ {
UNREFERENCED_PARAMETER(pUIContextData); UNREFERENCED_PARAMETER(pUIContextData);
UNREFERENCED_PARAMETER(dwUIContextDataSize); UNREFERENCED_PARAMETER(dwUIContextDataSize);
UNREFERENCED_PARAMETER(pEapOutput);
// Default implementation does nothing with context data. // Default implementation does nothing with context data.
return EapPeerMethodResponseActionNone;
} }
@ -145,16 +144,12 @@ void eap::method::get_response_attributes(_Inout_ EapAttributes *pAttribs)
} }
void eap::method::set_response_attributes( EapPeerMethodResponseAction eap::method::set_response_attributes(_In_ const EapAttributes *pAttribs)
_In_ const EapAttributes *pAttribs,
_Out_ EapPeerMethodOutput *pEapOutput)
{ {
UNREFERENCED_PARAMETER(pAttribs); UNREFERENCED_PARAMETER(pAttribs);
assert(pEapOutput);
// Default implementation discards the EAP attributes. // Default implementation does nothing with EAP attributes.
pEapOutput->action = EapPeerMethodResponseActionDiscard; return EapPeerMethodResponseActionNone;
pEapOutput->fAllowNotifications = FALSE;
} }

View File

@ -93,10 +93,9 @@ namespace eap
/// ///
/// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
/// ///
virtual void process_request_packet( virtual EapPeerMethodResponseAction process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize, _In_ DWORD dwReceivedPacketSize);
_Out_ EapPeerMethodOutput *pEapOutput);
/// ///
/// Obtains a response packet from the EAP method. /// Obtains a response packet from the EAP method.
@ -139,10 +138,9 @@ namespace eap
/// ///
/// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx) /// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx)
/// ///
virtual void set_ui_context( virtual EapPeerMethodResponseAction set_ui_context(
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData, _In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
_In_ DWORD dwUIContextDataSize, _In_ DWORD dwUIContextDataSize);
_Out_ EapPeerMethodOutput *pEapOutput);
/// @} /// @}
@ -161,9 +159,7 @@ namespace eap
/// ///
/// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx) /// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx)
/// ///
virtual void set_response_attributes( virtual EapPeerMethodResponseAction set_response_attributes(_In_ const EapAttributes *pAttribs);
_In_ const EapAttributes *pAttribs,
_Out_ EapPeerMethodOutput *pEapOutput);
/// @} /// @}
@ -171,24 +167,22 @@ namespace eap
/// ///
/// Converts EapHost peer action to output structure. /// Converts EapHost peer action to output structure.
/// ///
/// \param[in ] action EapHost peer action /// \param[in] action EapHost peer action
/// \param[out] pEapOutput EAP method output structure
/// ///
inline void action_to_output( /// \returns EAP method output action
_In_ EapHostPeerResponseAction action, ///
_Out_ EapPeerMethodOutput *pEapOutput) inline EapPeerMethodResponseAction action_h2p(_In_ EapHostPeerResponseAction action)
{ {
switch (action) { switch (action) {
case EapHostPeerResponseDiscard : pEapOutput->action = EapPeerMethodResponseActionDiscard ; break; case EapHostPeerResponseDiscard : return EapPeerMethodResponseActionDiscard ;
case EapHostPeerResponseSend : pEapOutput->action = EapPeerMethodResponseActionSend ; break; case EapHostPeerResponseSend : return EapPeerMethodResponseActionSend ;
case EapHostPeerResponseResult : pEapOutput->action = EapPeerMethodResponseActionResult ; break; case EapHostPeerResponseResult : return EapPeerMethodResponseActionResult ;
case EapHostPeerResponseInvokeUi : pEapOutput->action = EapPeerMethodResponseActionInvokeUI; break; case EapHostPeerResponseInvokeUi : return EapPeerMethodResponseActionInvokeUI;
case EapHostPeerResponseRespond : pEapOutput->action = EapPeerMethodResponseActionRespond ; break; case EapHostPeerResponseRespond : return EapPeerMethodResponseActionRespond ;
case EapHostPeerResponseStartAuthentication: pEapOutput->action = EapPeerMethodResponseActionDiscard ; break; // The session could not be found. So the supplicant either needs to start session again with the same packet or discard the packet. case EapHostPeerResponseStartAuthentication: return EapPeerMethodResponseActionDiscard ; // The session could not be found. So the supplicant either needs to start session again with the same packet or discard the packet.
case EapHostPeerResponseNone : pEapOutput->action = EapPeerMethodResponseActionNone ; break; case EapHostPeerResponseNone : return EapPeerMethodResponseActionNone ;
default : throw std::invalid_argument(winstd::string_printf(__FUNCTION__ " Unknown action (%u).", action).c_str()); default : throw std::invalid_argument(winstd::string_printf(__FUNCTION__ " Unknown action (%u).", action).c_str());
} }
pEapOutput->fAllowNotifications = TRUE;
} }
protected: protected:

View File

@ -102,13 +102,11 @@ void eap::method_eaphost::end_session()
} }
void eap::method_eaphost::process_request_packet( EapPeerMethodResponseAction eap::method_eaphost::process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize, _In_ DWORD dwReceivedPacketSize)
_Out_ EapPeerMethodOutput *pEapOutput)
{ {
assert(pReceivedPacket || dwReceivedPacketSize == 0); assert(pReceivedPacket || dwReceivedPacketSize == 0);
assert(pEapOutput);
m_module.log_event(&EAPMETHOD_PACKET_RECV, event_data((unsigned int)m_cfg.get_method_id()), event_data((unsigned int)dwReceivedPacketSize), event_data::blank); m_module.log_event(&EAPMETHOD_PACKET_RECV, event_data((unsigned int)m_cfg.get_method_id()), event_data((unsigned int)dwReceivedPacketSize), event_data::blank);
@ -123,7 +121,7 @@ void eap::method_eaphost::process_request_packet(
&error._Myptr); &error._Myptr);
if (dwResult == ERROR_SUCCESS) { if (dwResult == ERROR_SUCCESS) {
// Packet successfuly processed. // Packet successfuly processed.
action_to_output(action, pEapOutput); return action_h2p(action);
} else if (error) } else if (error)
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerProcessReceivedPacket failed."); throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerProcessReceivedPacket failed.");
else else
@ -212,13 +210,10 @@ void eap::method_eaphost::get_ui_context(
} }
void eap::method_eaphost::set_ui_context( EapPeerMethodResponseAction eap::method_eaphost::set_ui_context(
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData, _In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
_In_ DWORD dwUIContextDataSize, _In_ DWORD dwUIContextDataSize)
_Out_ EapPeerMethodOutput *pEapOutput)
{ {
assert(pEapOutput);
// Set EapHost peer UI context data. // Set EapHost peer UI context data.
EapHostPeerResponseAction action; EapHostPeerResponseAction action;
eap_error_runtime error; eap_error_runtime error;
@ -230,7 +225,7 @@ void eap::method_eaphost::set_ui_context(
&error._Myptr); &error._Myptr);
if (dwResult == ERROR_SUCCESS) { if (dwResult == ERROR_SUCCESS) {
// UI context data successfuly returned. // UI context data successfuly returned.
action_to_output(action, pEapOutput); return action_h2p(action);
} else if (error) } else if (error)
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerSetUIContext failed."); throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerSetUIContext failed.");
else else
@ -255,9 +250,7 @@ void eap::method_eaphost::get_response_attributes(_Inout_ EapAttributes *pAttrib
} }
void eap::method_eaphost::set_response_attributes( EapPeerMethodResponseAction eap::method_eaphost::set_response_attributes(_In_ const EapAttributes *pAttribs)
_In_ const EapAttributes *pAttribs,
_Out_ EapPeerMethodOutput *pEapOutput)
{ {
// Set response attributes for EapHost peer. // Set response attributes for EapHost peer.
EapHostPeerResponseAction action; EapHostPeerResponseAction action;
@ -269,7 +262,7 @@ void eap::method_eaphost::set_response_attributes(
&error._Myptr); &error._Myptr);
if (dwResult == ERROR_SUCCESS) { if (dwResult == ERROR_SUCCESS) {
// Response attributes successfuly set. // Response attributes successfuly set.
action_to_output(action, pEapOutput); return action_h2p(action);
} else if (error) } else if (error)
throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerGetResponseAttributes failed."); throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerGetResponseAttributes failed.");
else else

View File

@ -87,10 +87,9 @@ namespace eap
/// ///
/// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
/// ///
virtual void process_request_packet( virtual EapPeerMethodResponseAction process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize, _In_ DWORD dwReceivedPacketSize);
_Out_ EapPeerMethodOutput *pEapOutput);
/// @} /// @}

View File

@ -87,13 +87,11 @@ void eap::method_mschapv2::begin_session(
} }
void eap::method_mschapv2::process_request_packet( EapPeerMethodResponseAction eap::method_mschapv2::process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize, _In_ DWORD dwReceivedPacketSize)
_Out_ EapPeerMethodOutput *pEapOutput)
{ {
assert(pReceivedPacket || dwReceivedPacketSize == 0); assert(pReceivedPacket || dwReceivedPacketSize == 0);
assert(pEapOutput);
m_module.log_event(&EAPMETHOD_PACKET_RECV, event_data((unsigned int)eap_type_legacy_mschapv2), event_data((unsigned int)dwReceivedPacketSize), event_data::blank); m_module.log_event(&EAPMETHOD_PACKET_RECV, event_data((unsigned int)eap_type_legacy_mschapv2), event_data((unsigned int)dwReceivedPacketSize), event_data::blank);
@ -130,22 +128,22 @@ void eap::method_mschapv2::process_request_packet(
m_phase = phase_challenge_server; m_phase = phase_challenge_server;
m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point. m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point.
break; return EapPeerMethodResponseActionSend;
} }
case phase_challenge_server: { case phase_challenge_server: {
process_packet(pReceivedPacket, dwReceivedPacketSize); process_packet(pReceivedPacket, dwReceivedPacketSize);
if (m_success) if (m_success)
m_phase = phase_finished; m_phase = phase_finished;
break; return EapPeerMethodResponseActionNone;
} }
case phase_finished: case phase_finished:
break; return EapPeerMethodResponseActionNone;
}
pEapOutput->fAllowNotifications = TRUE; default:
pEapOutput->action = EapPeerMethodResponseActionSend; throw invalid_argument(string_printf(__FUNCTION__ " Unknown phase (phase %u).", m_phase).c_str());
}
} }

View File

@ -85,10 +85,9 @@ namespace eap
/// ///
/// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
/// ///
virtual void process_request_packet( virtual EapPeerMethodResponseAction process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize, _In_ DWORD dwReceivedPacketSize);
_Out_ EapPeerMethodOutput *pEapOutput);
/// @} /// @}

View File

@ -69,14 +69,12 @@ void eap::method_pap::begin_session(
} }
void eap::method_pap::process_request_packet( EapPeerMethodResponseAction eap::method_pap::process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize, _In_ DWORD dwReceivedPacketSize)
_Out_ EapPeerMethodOutput *pEapOutput)
{ {
UNREFERENCED_PARAMETER(pReceivedPacket); UNREFERENCED_PARAMETER(pReceivedPacket);
assert(pReceivedPacket || dwReceivedPacketSize == 0); assert(pReceivedPacket || dwReceivedPacketSize == 0);
assert(pEapOutput);
m_module.log_event(&EAPMETHOD_PACKET_RECV, event_data((unsigned int)eap_type_legacy_pap), event_data((unsigned int)dwReceivedPacketSize), event_data::blank); m_module.log_event(&EAPMETHOD_PACKET_RECV, event_data((unsigned int)eap_type_legacy_pap), event_data((unsigned int)dwReceivedPacketSize), event_data::blank);
@ -99,13 +97,13 @@ void eap::method_pap::process_request_packet(
m_phase = phase_finished; m_phase = phase_finished;
m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point. m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point.
break; return EapPeerMethodResponseActionSend;
} }
case phase_finished: case phase_finished:
break; return EapPeerMethodResponseActionNone;
}
pEapOutput->fAllowNotifications = TRUE; default:
pEapOutput->action = EapPeerMethodResponseActionSend; throw invalid_argument(string_printf(__FUNCTION__ " Unknown phase (phase %u).", m_phase).c_str());
}
} }

View File

@ -107,10 +107,9 @@ namespace eap
/// ///
/// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
/// ///
virtual void process_request_packet( virtual EapPeerMethodResponseAction process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize, _In_ DWORD dwReceivedPacketSize);
_Out_ EapPeerMethodOutput *pEapOutput);
/// ///
/// Obtains a response packet from the EAP method. /// Obtains a response packet from the EAP method.
@ -291,13 +290,13 @@ namespace eap
/// ///
/// Process handshake /// Process handshake
/// ///
void process_handshake(); EapPeerMethodResponseAction process_handshake();
#endif #endif
/// ///
/// Process application data /// Process application data
/// ///
void process_application_data(); EapPeerMethodResponseAction process_application_data();
/// ///
/// Processes a TLS application_data message /// Processes a TLS application_data message
@ -307,7 +306,7 @@ namespace eap
/// \param[in] msg TLS application_data message data /// \param[in] msg TLS application_data message data
/// \param[in] size_msg TLS application_data message data size /// \param[in] size_msg TLS application_data message data size
/// ///
virtual void process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg); virtual EapPeerMethodResponseAction process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg);
/// @} /// @}

View File

@ -246,13 +246,11 @@ void eap::method_tls::begin_session(
} }
void eap::method_tls::process_request_packet( EapPeerMethodResponseAction eap::method_tls::process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize, _In_ DWORD dwReceivedPacketSize)
_Out_ EapPeerMethodOutput *pEapOutput)
{ {
assert(pReceivedPacket && dwReceivedPacketSize >= 4); assert(pReceivedPacket && dwReceivedPacketSize >= 4);
assert(pEapOutput);
// Is this a valid EAP-TLS packet? // Is this a valid EAP-TLS packet?
if (dwReceivedPacketSize < 6) if (dwReceivedPacketSize < 6)
@ -265,9 +263,7 @@ void eap::method_tls::process_request_packet(
m_packet_res.m_id = ((const EapPacket*)pReceivedPacket)->Id; m_packet_res.m_id = ((const EapPacket*)pReceivedPacket)->Id;
m_packet_res.m_flags = 0; m_packet_res.m_flags = 0;
m_packet_res.m_data.clear(); m_packet_res.m_data.clear();
pEapOutput->fAllowNotifications = FALSE; return EapPeerMethodResponseActionSend;
pEapOutput->action = EapPeerMethodResponseActionSend;
return;
} }
if (m_packet_res.m_flags & packet_tls::flags_res_more_frag) { if (m_packet_res.m_flags & packet_tls::flags_res_more_frag) {
@ -275,9 +271,7 @@ void eap::method_tls::process_request_packet(
if (m_packet_req.is_ack(m_packet_res.m_id)) { if (m_packet_req.is_ack(m_packet_res.m_id)) {
// This is the ACK of our fragmented message packet. Send the next fragment. // This is the ACK of our fragmented message packet. Send the next fragment.
m_packet_res.m_id++; m_packet_res.m_id++;
pEapOutput->fAllowNotifications = FALSE; return EapPeerMethodResponseActionSend;
pEapOutput->action = EapPeerMethodResponseActionSend;
return;
} else } else
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, string_printf(__FUNCTION__ " ACK expected, received %u-%u-%x.", m_packet_req.m_code, m_packet_req.m_id, m_packet_req.m_flags)); throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, string_printf(__FUNCTION__ " ACK expected, received %u-%u-%x.", m_packet_req.m_code, m_packet_req.m_id, m_packet_req.m_flags));
} }
@ -286,6 +280,7 @@ void eap::method_tls::process_request_packet(
m_packet_res.m_id = m_packet_req.m_id; m_packet_res.m_id = m_packet_req.m_id;
m_packet_res.m_flags = 0; m_packet_res.m_flags = 0;
EapPeerMethodResponseAction action = EapPeerMethodResponseActionNone;
user_impersonator impersonating(m_user_ctx); user_impersonator impersonating(m_user_ctx);
#if EAP_TLS < EAP_TLS_SCHANNEL #if EAP_TLS < EAP_TLS_SCHANNEL
@ -325,6 +320,7 @@ void eap::method_tls::process_request_packet(
m_packet_res.m_data.insert(m_packet_res.m_data.end(), msg_client_hello.begin(), msg_client_hello.end()); m_packet_res.m_data.insert(m_packet_res.m_data.end(), msg_client_hello.begin(), msg_client_hello.end());
m_phase = phase_server_hello; m_phase = phase_server_hello;
action = EapPeerMethodResponseActionSend;
break; break;
} }
@ -427,12 +423,14 @@ void eap::method_tls::process_request_packet(
// Go to application data phase. And allow piggybacking of the first data message. // Go to application data phase. And allow piggybacking of the first data message.
m_phase = phase_application_data; m_phase = phase_application_data;
m_session_resumed = true; m_session_resumed = true;
process_application_data(NULL, 0); action = process_application_data(NULL, 0);
} else { } else {
m_session_resumed = false; m_session_resumed = false;
m_phase = phase_change_cipher_spec; m_phase = phase_change_cipher_spec;
m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point. m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point.
action = EapPeerMethodResponseActionSend;
} }
break; break;
} }
@ -440,13 +438,20 @@ void eap::method_tls::process_request_packet(
// Wait in this phase until server sends change cipher spec and finish. // Wait in this phase until server sends change cipher spec and finish.
if (m_state_server.m_alg_encrypt && m_handshake[tls_handshake_type_finished]) { if (m_state_server.m_alg_encrypt && m_handshake[tls_handshake_type_finished]) {
m_phase = phase_application_data; m_phase = phase_application_data;
process_application_data(NULL, 0); action = process_application_data(NULL, 0);
} else {
// Ignore content of the message and keep replying with ACK packet until change cipher spec is delivered.
action = EapPeerMethodResponseActionSend;
} }
break; break;
case phase_application_data: case phase_application_data:
if (m_handshake[tls_handshake_type_hello_request]) if (m_handshake[tls_handshake_type_hello_request])
m_phase = phase_client_hello; m_phase = phase_client_hello;
break;
default:
throw invalid_argument(string_printf(__FUNCTION__ " Unknown phase (phase %u).", m_phase).c_str());
} }
#else #else
if (((const EapPacket*)pReceivedPacket)->Code == EapCodeRequest && (m_packet_req.m_flags & packet_tls::flags_req_start)) { if (((const EapPacket*)pReceivedPacket)->Code == EapCodeRequest && (m_packet_req.m_flags & packet_tls::flags_req_start)) {
@ -462,20 +467,21 @@ void eap::method_tls::process_request_packet(
switch (m_phase) { switch (m_phase) {
case phase_handshake_init: case phase_handshake_init:
case phase_handshake_cont: case phase_handshake_cont:
process_handshake(); action = process_handshake();
break; break;
case phase_application_data: case phase_application_data:
process_application_data(); action = process_application_data();
break; break;
default:
throw invalid_argument(string_printf(__FUNCTION__ " Unknown phase (phase %u).", m_phase).c_str());
} }
#endif #endif
pEapOutput->fAllowNotifications = TRUE;
pEapOutput->action = EapPeerMethodResponseActionSend;
// EAP-Request packet was processed. Clear its data since we use the absence of data to detect first of fragmented message packages. // EAP-Request packet was processed. Clear its data since we use the absence of data to detect first of fragmented message packages.
m_packet_req.m_data.clear(); m_packet_req.m_data.clear();
return action;
} }
@ -1105,7 +1111,7 @@ void eap::method_tls::process_handshake(_In_bytecount_(size_msg) const void *_ms
#else #else
void eap::method_tls::process_handshake() EapPeerMethodResponseAction eap::method_tls::process_handshake()
{ {
// Prepare input buffer(s). // Prepare input buffer(s).
SecBuffer buf_in[] = { SecBuffer buf_in[] = {
@ -1193,32 +1199,35 @@ void eap::method_tls::process_handshake()
derive_challenge(); derive_challenge();
m_phase = phase_application_data; m_phase = phase_application_data;
process_application_data(m_sc_queue.data(), m_sc_queue.size()); return process_application_data(m_sc_queue.data(), m_sc_queue.size());
} else { } else {
m_phase = phase_handshake_cont; m_phase = phase_handshake_cont;
m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point. m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point.
return EapPeerMethodResponseActionSend;
} }
} else if (status == SEC_E_INCOMPLETE_MESSAGE) { } else if (status == SEC_E_INCOMPLETE_MESSAGE) {
// Schannel neeeds more data. Send ACK packet to server to send more. // Schannel neeeds more data. Send ACK packet to server to send more.
return EapPeerMethodResponseActionSend;
} else if (FAILED(status)) { } else if (FAILED(status)) {
if (m_sc_ctx.m_attrib & ISC_RET_EXTENDED_ERROR) { if (m_sc_ctx.m_attrib & ISC_RET_EXTENDED_ERROR) {
// Send alert via EAP. Not that EAP will transmit it once we throw this is an error... // Send alert.
assert(buf_out[1].BufferType == SECBUFFER_ALERT); assert(buf_out[1].BufferType == SECBUFFER_ALERT);
assert(m_sc_ctx.m_attrib & ISC_RET_ALLOCATED_MEMORY); assert(m_sc_ctx.m_attrib & ISC_RET_ALLOCATED_MEMORY);
m_packet_res.m_data.assign(reinterpret_cast<const unsigned char*>(buf_out[1].pvBuffer), reinterpret_cast<const unsigned char*>(buf_out[1].pvBuffer) + buf_out[1].cbBuffer); m_packet_res.m_data.assign(reinterpret_cast<const unsigned char*>(buf_out[1].pvBuffer), reinterpret_cast<const unsigned char*>(buf_out[1].pvBuffer) + buf_out[1].cbBuffer);
} return EapPeerMethodResponseActionSend;
} else
throw sec_runtime_error(status, __FUNCTION__ " Schannel error."); throw sec_runtime_error(status, __FUNCTION__ " Schannel error.");
} }
return EapPeerMethodResponseActionNone;
} }
void eap::method_tls::process_application_data() EapPeerMethodResponseAction eap::method_tls::process_application_data()
{ {
if (m_sc_queue.empty()) { if (m_sc_queue.empty()) {
// An ACK packet received. Nothing to unencrypt. // An ACK packet received. Nothing to unencrypt.
process_application_data(NULL, 0); return process_application_data(NULL, 0);
return;
} }
if (!(m_sc_ctx.m_attrib & ISC_RET_CONFIDENTIALITY)) if (!(m_sc_ctx.m_attrib & ISC_RET_CONFIDENTIALITY))
@ -1244,10 +1253,18 @@ void eap::method_tls::process_application_data()
// Decrypt the message. // Decrypt the message.
SECURITY_STATUS status = DecryptMessage(m_sc_ctx, &buf_desc, 0, NULL); SECURITY_STATUS status = DecryptMessage(m_sc_ctx, &buf_desc, 0, NULL);
if (status == SEC_E_OK) { if (status == SEC_E_OK) {
EapPeerMethodResponseAction action = EapPeerMethodResponseActionNone;
// Find SECBUFFER_DATA buffer(s) and process data. // Find SECBUFFER_DATA buffer(s) and process data.
for (size_t i = 0; i < _countof(buf); i++) for (size_t i = 0; i < _countof(buf); i++)
if (buf[i].BufferType == SECBUFFER_DATA) if (buf[i].BufferType == SECBUFFER_DATA) {
process_application_data(buf[i].pvBuffer, buf[i].cbBuffer); action = process_application_data(buf[i].pvBuffer, buf[i].cbBuffer);
if (action == EapPeerMethodResponseActionDiscard) {
// Request is to be discarded as a whole.
m_sc_queue.clear();
return EapPeerMethodResponseActionDiscard;
}
}
// Find SECBUFFER_EXTRA buffer(s) and queue data for the next time. // Find SECBUFFER_EXTRA buffer(s) and queue data for the next time.
std::vector<unsigned char> extra; std::vector<unsigned char> extra;
@ -1255,28 +1272,37 @@ void eap::method_tls::process_application_data()
if (buf[i].BufferType == SECBUFFER_EXTRA) if (buf[i].BufferType == SECBUFFER_EXTRA)
extra.insert(extra.end(), reinterpret_cast<const unsigned char*>(buf[i].pvBuffer), reinterpret_cast<const unsigned char*>(buf[i].pvBuffer) + buf[i].cbBuffer); extra.insert(extra.end(), reinterpret_cast<const unsigned char*>(buf[i].pvBuffer), reinterpret_cast<const unsigned char*>(buf[i].pvBuffer) + buf[i].cbBuffer);
m_sc_queue = std::move(extra); m_sc_queue = std::move(extra);
return action;
} else if (status == SEC_E_INCOMPLETE_MESSAGE) { } else if (status == SEC_E_INCOMPLETE_MESSAGE) {
// Schannel neeeds more data. Send ACK packet to server to send more. // Schannel neeeds more data. Send ACK packet to server to send more.
return EapPeerMethodResponseActionSend;
} else if (status == SEC_I_CONTEXT_EXPIRED) { } else if (status == SEC_I_CONTEXT_EXPIRED) {
// Server initiated connection shutdown. // Server initiated connection shutdown.
m_sc_queue.clear(); m_sc_queue.clear();
m_phase = phase_shutdown; m_phase = phase_shutdown;
return EapPeerMethodResponseActionNone;
} else if (status == SEC_I_RENEGOTIATE) { } else if (status == SEC_I_RENEGOTIATE) {
// Re-negotiation required. // Re-negotiation required.
m_sc_queue.clear(); m_sc_queue.clear();
m_phase = phase_handshake_init; m_phase = phase_handshake_init;
process_handshake(); process_handshake();
return EapPeerMethodResponseActionSend;
} else if (FAILED(status)) } else if (FAILED(status))
throw sec_runtime_error(status, __FUNCTION__ " Schannel error."); throw sec_runtime_error(status, __FUNCTION__ " Schannel error.");
return EapPeerMethodResponseActionNone;
} }
#endif #endif
void eap::method_tls::process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg) EapPeerMethodResponseAction eap::method_tls::process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg)
{ {
UNREFERENCED_PARAMETER(msg); UNREFERENCED_PARAMETER(msg);
UNREFERENCED_PARAMETER(size_msg); UNREFERENCED_PARAMETER(size_msg);
return EapPeerMethodResponseActionNone;
} }

View File

@ -94,10 +94,9 @@ namespace eap
/// ///
/// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
/// ///
virtual void process_request_packet( virtual EapPeerMethodResponseAction process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize, _In_ DWORD dwReceivedPacketSize);
_Out_ EapPeerMethodOutput *pEapOutput);
/// ///
/// Obtains a response packet from the EAP method. /// Obtains a response packet from the EAP method.
@ -140,10 +139,9 @@ namespace eap
/// ///
/// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx) /// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx)
/// ///
virtual void set_ui_context( virtual EapPeerMethodResponseAction set_ui_context(
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData, _In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
_In_ DWORD dwUIContextDataSize, _In_ DWORD dwUIContextDataSize);
_Out_ EapPeerMethodOutput *pEapOutput);
/// @} /// @}
@ -162,9 +160,7 @@ namespace eap
/// ///
/// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx) /// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx)
/// ///
virtual void set_response_attributes( virtual EapPeerMethodResponseAction set_response_attributes(_In_ const EapAttributes *pAttribs);
_In_ const EapAttributes *pAttribs,
_Out_ EapPeerMethodOutput *pEapOutput);
/// @} /// @}
@ -187,7 +183,7 @@ namespace eap
/// \param[in] msg Application message data /// \param[in] msg Application message data
/// \param[in] size_msg Application message data size /// \param[in] size_msg Application message data size
/// ///
virtual void process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg); virtual EapPeerMethodResponseAction process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg);
protected: protected:
#pragma warning(suppress: 4480) #pragma warning(suppress: 4480)

View File

@ -89,10 +89,9 @@ void eap::method_ttls::end_session()
} }
void eap::method_ttls::process_request_packet( EapPeerMethodResponseAction eap::method_ttls::process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize, _In_ DWORD dwReceivedPacketSize)
_Out_ EapPeerMethodOutput *pEapOutput)
{ {
if (((const EapPacket*)pReceivedPacket)->Code == EapCodeRequest && (((const EapPacket*)pReceivedPacket)->Data[1] & packet_ttls::flags_start)) { if (((const EapPacket*)pReceivedPacket)->Code == EapCodeRequest && (((const EapPacket*)pReceivedPacket)->Data[1] & packet_ttls::flags_start)) {
// This is a start EAP-TTLS packet. // This is a start EAP-TTLS packet.
@ -104,7 +103,7 @@ void eap::method_ttls::process_request_packet(
} }
// Do the TLS. // Do the TLS.
method_tls::process_request_packet(pReceivedPacket, dwReceivedPacketSize, pEapOutput); return method_tls::process_request_packet(pReceivedPacket, dwReceivedPacketSize);
} }
@ -155,14 +154,12 @@ void eap::method_ttls::get_ui_context(
} }
void eap::method_ttls::set_ui_context( EapPeerMethodResponseAction eap::method_ttls::set_ui_context(
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData, _In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
_In_ DWORD dwUIContextDataSize, _In_ DWORD dwUIContextDataSize)
_Out_ EapPeerMethodOutput *pEapOutput)
{ {
UNREFERENCED_PARAMETER(pUIContextData); UNREFERENCED_PARAMETER(pUIContextData);
UNREFERENCED_PARAMETER(dwUIContextDataSize); UNREFERENCED_PARAMETER(dwUIContextDataSize);
UNREFERENCED_PARAMETER(pEapOutput);
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported."); throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported.");
} }
@ -176,12 +173,9 @@ void eap::method_ttls::get_response_attributes(_Inout_ EapAttributes *pAttribs)
} }
void eap::method_ttls::set_response_attributes( EapPeerMethodResponseAction eap::method_ttls::set_response_attributes(_In_ const EapAttributes *pAttribs)
_In_ const EapAttributes *pAttribs,
_Out_ EapPeerMethodOutput *pEapOutput)
{ {
UNREFERENCED_PARAMETER(pAttribs); UNREFERENCED_PARAMETER(pAttribs);
UNREFERENCED_PARAMETER(pEapOutput);
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported."); throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported.");
} }
@ -273,7 +267,7 @@ void eap::method_ttls::derive_challenge()
} }
void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg) EapPeerMethodResponseAction eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg)
{ {
// Prepare inner authentication. // Prepare inner authentication.
#if EAP_TLS < EAP_TLS_SCHANNEL #if EAP_TLS < EAP_TLS_SCHANNEL
@ -282,7 +276,7 @@ void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const v
if (m_session_resumed) { if (m_session_resumed) {
// On reconnect we do not need to do inner re-authentication. // On reconnect we do not need to do inner re-authentication.
return; return EapPeerMethodResponseActionNone;
} }
#else #else
if (!(m_sc_ctx.m_attrib & ISC_RET_CONFIDENTIALITY)) if (!(m_sc_ctx.m_attrib & ISC_RET_CONFIDENTIALITY))
@ -292,13 +286,12 @@ void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const v
if (SUCCEEDED(QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_SESSION_INFO, &session_info)) && (session_info.dwFlags & SSL_SESSION_RECONNECT)) { if (SUCCEEDED(QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_SESSION_INFO, &session_info)) && (session_info.dwFlags & SSL_SESSION_RECONNECT)) {
// On reconnect we do not need to do inner re-authentication. // On reconnect we do not need to do inner re-authentication.
// According to MSDN QueryContextAttributes(SECPKG_ATTR_SESSION_INFO) works from Windows 7 on. Therefore behaviour might vary. // According to MSDN QueryContextAttributes(SECPKG_ATTR_SESSION_INFO) works from Windows 7 on. Therefore behaviour might vary.
return; return EapPeerMethodResponseActionNone;
} }
#endif #endif
EapPeerMethodOutput eap_output = {}; EapPeerMethodResponseAction action = m_inner->process_request_packet(msg, (DWORD)size_msg);
m_inner->process_request_packet(msg, (DWORD)size_msg, &eap_output); switch (action) {
switch (eap_output.action) {
case EapPeerMethodResponseActionSend: { case EapPeerMethodResponseActionSend: {
// Retrieve inner packet and send it. // Retrieve inner packet and send it.
@ -356,6 +349,8 @@ void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const v
} }
default: default:
throw invalid_argument(string_printf(__FUNCTION__ " Inner method returned an unsupported action (action %u).", eap_output.action).c_str()); throw invalid_argument(string_printf(__FUNCTION__ " Inner method returned an unsupported action (action %u).", action).c_str());
} }
return action;
} }

View File

@ -254,7 +254,9 @@ void eap::peer_ttls::process_request_packet(
_Out_ EapPeerMethodOutput *pEapOutput) _Out_ EapPeerMethodOutput *pEapOutput)
{ {
assert(dwReceivedPacketSize == ntohs(*(WORD*)pReceivedPacket->Length)); assert(dwReceivedPacketSize == ntohs(*(WORD*)pReceivedPacket->Length));
static_cast<session*>(hSession)->m_method->process_request_packet(pReceivedPacket, dwReceivedPacketSize, pEapOutput); assert(pEapOutput);
pEapOutput->action = static_cast<session*>(hSession)->m_method->process_request_packet(pReceivedPacket, dwReceivedPacketSize);
pEapOutput->fAllowNotifications = TRUE;
} }
@ -318,7 +320,9 @@ void eap::peer_ttls::set_ui_context(
_In_ DWORD dwUIContextDataSize, _In_ DWORD dwUIContextDataSize,
_Out_ EapPeerMethodOutput *pEapOutput) _Out_ EapPeerMethodOutput *pEapOutput)
{ {
static_cast<session*>(hSession)->m_method->set_ui_context(pUIContextData, dwUIContextDataSize, pEapOutput); assert(pEapOutput);
pEapOutput->action = static_cast<session*>(hSession)->m_method->set_ui_context(pUIContextData, dwUIContextDataSize);
pEapOutput->fAllowNotifications = TRUE;
} }
@ -335,7 +339,9 @@ void eap::peer_ttls::set_response_attributes(
_In_ const EapAttributes *pAttribs, _In_ const EapAttributes *pAttribs,
_Out_ EapPeerMethodOutput *pEapOutput) _Out_ EapPeerMethodOutput *pEapOutput)
{ {
static_cast<session*>(hSession)->m_method->set_response_attributes(pAttribs, pEapOutput); assert(pEapOutput);
pEapOutput->action = static_cast<session*>(hSession)->m_method->set_response_attributes(pAttribs);
pEapOutput->fAllowNotifications = TRUE;
} }