Own TLS updated to keep it alive (now that the fuss around outer/inner methods settled)

This commit is contained in:
Simon Rozman 2016-08-29 20:40:37 +02:00
parent a7c8052ee2
commit cafd786e19
4 changed files with 50 additions and 34 deletions

View File

@ -362,12 +362,12 @@ namespace eap
/// Process handshake /// Process handshake
/// ///
void process_handshake(); void process_handshake();
#endif
/// ///
/// Process application data /// Process application data
/// ///
void process_application_data(); void process_application_data();
#endif
/// ///
/// Processes a TLS application_data message /// Processes a TLS application_data message

View File

@ -544,14 +544,22 @@ void eap::method_tls::process_request_packet(
sanitizing_blob msg_finished(make_message(tls_message_type_handshake, make_finished())); sanitizing_blob msg_finished(make_message(tls_message_type_handshake, make_finished()));
m_packet_res.m_data.insert(m_packet_res.m_data.end(), msg_finished.begin(), msg_finished.end()); m_packet_res.m_data.insert(m_packet_res.m_data.end(), msg_finished.begin(), msg_finished.end());
m_phase = m_handshake[tls_handshake_type_finished] ? phase_application_data : phase_change_cipher_spec; if (m_handshake[tls_handshake_type_finished]) {
// Go to application data phase. And allow piggybacking of the first data message.
m_phase = phase_application_data;
process_application_data(NULL, 0);
} else {
m_phase = phase_change_cipher_spec;
}
break; break;
} }
case phase_change_cipher_spec: case phase_change_cipher_spec:
// 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);
}
break; break;
case phase_application_data: case phase_application_data:
@ -702,20 +710,29 @@ void eap::method_tls::get_result(
} }
case EapPeerMethodResultFailure: case EapPeerMethodResultFailure:
#if EAP_TLS < EAP_TLS_SCHANNEL
m_module.log_event(
m_phase < phase_change_cipher_spec ? &EAPMETHOD_METHOD_FAILURE_INIT :
m_phase < phase_application_data ? &EAPMETHOD_METHOD_FAILURE_HANDSHAKE : &EAPMETHOD_METHOD_FAILURE,
event_data((unsigned int)eap_type_tls), event_data::blank);
// Mark credentials as failed, so GUI can re-prompt user.
// But be careful: do so only if this happened after transition from handshake to application data phase.
m_cfg.m_auth_failed = m_phase >= phase_application_data;
// Clear session resumption data.
m_cfg.m_session_id.clear();
m_cfg.m_master_secret.clear();
#else
m_module.log_event( m_module.log_event(
m_phase_prev < phase_handshake_cont ? &EAPMETHOD_METHOD_FAILURE_INIT : m_phase_prev < phase_handshake_cont ? &EAPMETHOD_METHOD_FAILURE_INIT :
m_phase_prev < phase_application_data ? &EAPMETHOD_METHOD_FAILURE_HANDSHAKE : &EAPMETHOD_METHOD_FAILURE, m_phase_prev < phase_application_data ? &EAPMETHOD_METHOD_FAILURE_HANDSHAKE : &EAPMETHOD_METHOD_FAILURE,
event_data((unsigned int)eap_type_tls), event_data::blank); event_data((unsigned int)eap_type_tls), event_data::blank);
#if EAP_TLS < EAP_TLS_SCHANNEL
// Clear session resumption data.
m_cfg.m_session_id.clear();
m_cfg.m_master_secret.clear();
#endif
// Mark credentials as failed, so GUI can re-prompt user. // Mark credentials as failed, so GUI can re-prompt user.
// But be careful: do so only if this happened after transition from handshake to application data phase. // But be careful: do so only if this happened after transition from handshake to application data phase.
m_cfg.m_auth_failed = m_phase_prev < phase_application_data && m_phase >= phase_application_data; m_cfg.m_auth_failed = m_phase_prev < phase_application_data && m_phase >= phase_application_data;
#endif
// Do not report failure to EapHost, as it will not save updated configuration then. But we need it to save it, to alert user on next connection attempt. // Do not report failure to EapHost, as it will not save updated configuration then. But we need it to save it, to alert user on next connection attempt.
// EapHost is well aware of the failed condition. // EapHost is well aware of the failed condition.

View File

@ -140,7 +140,7 @@ namespace eap
/// ///
virtual void derive_msk(); virtual void derive_msk();
#else #endif
/// ///
/// Processes an application message /// Processes an application message
@ -150,8 +150,6 @@ namespace eap
/// ///
virtual void process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg); virtual void process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg);
#endif
protected: protected:
config_method_ttls &m_cfg; ///< EAP-TTLS method configuration config_method_ttls &m_cfg; ///< EAP-TTLS method configuration
credentials_ttls &m_cred; ///< EAP-TTLS credentials credentials_ttls &m_cred; ///< EAP-TTLS credentials

View File

@ -106,22 +106,6 @@ void eap::method_ttls::process_request_packet(
// Do the TLS. // Do the TLS.
method_tls::process_request_packet(pReceivedPacket, dwReceivedPacketSize, pEapOutput); method_tls::process_request_packet(pReceivedPacket, dwReceivedPacketSize, pEapOutput);
#if EAP_TLS < EAP_TLS_SCHANNEL
if (m_phase == phase_application_data) {
// Send inner authentication.
if (!m_state_client.m_alg_encrypt)
throw runtime_error(__FUNCTION__ " Refusing to continue with inner authentication unencrypted.");
m_module.log_event(&EAPMETHOD_TTLS_INNER_CRED, event_data((unsigned int)eap_type_ttls), event_data(m_cred.m_inner->get_name()), event_data::blank);
m_packet_res.m_code = EapCodeResponse;
m_packet_res.m_id = m_packet_req.m_id;
m_packet_res.m_flags = 0;
sanitizing_blob msg_application(make_message(tls_message_type_application_data, make_pap_client()));
m_packet_res.m_data.insert(m_packet_res.m_data.end(), msg_application.begin(), msg_application.end());
}
#endif
} }
@ -208,12 +192,16 @@ void eap::method_ttls::derive_msk()
_key_block += sizeof(tls_random); _key_block += sizeof(tls_random);
} }
#else #endif
void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg) void 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 (!m_state_client.m_alg_encrypt)
#else
if (!(m_sc_ctx.m_attrib & ISC_RET_CONFIDENTIALITY)) if (!(m_sc_ctx.m_attrib & ISC_RET_CONFIDENTIALITY))
#endif
throw runtime_error(__FUNCTION__ " Refusing to continue with inner authentication unencrypted."); throw runtime_error(__FUNCTION__ " Refusing to continue with inner authentication unencrypted.");
EapPeerMethodOutput eap_output = {}; EapPeerMethodOutput eap_output = {};
@ -239,17 +227,26 @@ void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const v
switch (eap_output.action) { switch (eap_output.action) {
case EapPeerMethodResponseActionSend: { case EapPeerMethodResponseActionSend: {
// Retrieve inner packet and send it. // Retrieve inner packet and send it.
SECURITY_STATUS status;
// Get maximum message sizes. // Get maximum message size and allocate memory for response packet.
#if EAP_TLS < EAP_TLS_SCHANNEL
m_packet_res.m_code = EapCodeResponse;
m_packet_res.m_id = m_packet_req.m_id;
m_packet_res.m_flags = 0;
DWORD size_data = m_size_inner_packet_max;
sanitizing_blob data(size_data, 0);
unsigned char *ptr_data = data.data();
#else
SecPkgContext_StreamSizes sizes; SecPkgContext_StreamSizes sizes;
status = QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_STREAM_SIZES, &sizes); SECURITY_STATUS status = QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_STREAM_SIZES, &sizes);
if (FAILED(status)) if (FAILED(status))
throw sec_runtime_error(status, __FUNCTION__ " Error getting Schannel required encryption sizes."); throw sec_runtime_error(status, __FUNCTION__ " Error getting Schannel required encryption sizes.");
sanitizing_blob data(sizes.cbHeader + m_size_inner_packet_max + sizes.cbTrailer, 0); sanitizing_blob data(sizes.cbHeader + m_size_inner_packet_max + sizes.cbTrailer, 0);
DWORD size_data = m_size_inner_packet_max; DWORD size_data = m_size_inner_packet_max;
unsigned char *ptr_data = data.data() + sizes.cbHeader; unsigned char *ptr_data = data.data() + sizes.cbHeader;
#endif
m_inner->get_response_packet((EapPacket*)ptr_data, &size_data); m_inner->get_response_packet((EapPacket*)ptr_data, &size_data);
if (eap_type_noneap_start <= eap_type && eap_type < eap_type_noneap_end) { if (eap_type_noneap_start <= eap_type && eap_type < eap_type_noneap_end) {
@ -257,6 +254,11 @@ void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const v
memmove(ptr_data, ptr_data + 4, size_data -= 4); memmove(ptr_data, ptr_data + 4, size_data -= 4);
} }
#if EAP_TLS < EAP_TLS_SCHANNEL
data.resize(size_data);
sanitizing_blob msg_application(make_message(tls_message_type_application_data, std::move(data)));
m_packet_res.m_data.insert(m_packet_res.m_data.end(), msg_application.begin(), msg_application.end());
#else
// Prepare input/output buffer(s). // Prepare input/output buffer(s).
SecBuffer buf[] = { SecBuffer buf[] = {
{ sizes.cbHeader, SECBUFFER_STREAM_HEADER , data.data() }, { sizes.cbHeader, SECBUFFER_STREAM_HEADER , data.data() },
@ -275,6 +277,7 @@ void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const v
if (FAILED(status)) if (FAILED(status))
throw sec_runtime_error(status, __FUNCTION__ " Error encrypting message."); throw sec_runtime_error(status, __FUNCTION__ " Error encrypting message.");
m_packet_res.m_data.insert(m_packet_res.m_data.end(), (const unsigned char*)buf[0].pvBuffer, (const unsigned char*)buf[0].pvBuffer + buf[0].cbBuffer + buf[1].cbBuffer + buf[2].cbBuffer); m_packet_res.m_data.insert(m_packet_res.m_data.end(), (const unsigned char*)buf[0].pvBuffer, (const unsigned char*)buf[0].pvBuffer + buf[0].cbBuffer + buf[1].cbBuffer + buf[2].cbBuffer);
#endif
break; break;
} }
@ -283,5 +286,3 @@ void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const v
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).", eap_output.action).c_str());
} }
} }
#endif