Cached credentials are correctly honored now

This commit is contained in:
Simon Rozman 2016-07-21 13:21:40 +02:00
parent fa84cf93b9
commit 6d8bd3f1c1
5 changed files with 75 additions and 64 deletions

View File

@ -237,11 +237,11 @@ DWORD APIENTRY EapPeerGetIdentity(
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" ppwszIdentity is NULL."))); g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" ppwszIdentity is NULL.")));
else { else {
eap::config_providers cfg(g_peer); eap::config_providers cfg(g_peer);
_EAPMETHOD_PEER::credentials_type cred(g_peer); _EAPMETHOD_PEER::credentials_type cred_in(g_peer), cred_out(g_peer);
if ( !g_peer.unpack(cfg, pConnectionData, dwConnectionDataSize, ppEapError) || if ( !g_peer.unpack(cfg, pConnectionData, dwConnectionDataSize, ppEapError) ||
dwUserDataSize && !g_peer.unpack(cred, pUserData, dwUserDataSize, ppEapError) || dwUserDataSize && !g_peer.unpack(cred_in, pUserData, dwUserDataSize, ppEapError) ||
!g_peer.get_identity(dwFlags, cfg, cred, hTokenImpersonateUser, pfInvokeUI, ppwszIdentity, ppEapError) || !g_peer.get_identity(dwFlags, cfg, dwUserDataSize ? &cred_in : NULL, cred_out, hTokenImpersonateUser, pfInvokeUI, ppwszIdentity, ppEapError) ||
!g_peer.pack(cred, ppUserDataOut, pdwUserDataOutSize, ppEapError)) !g_peer.pack(cred_out, ppUserDataOut, pdwUserDataOutSize, ppEapError))
{ {
if (*ppEapError) { if (*ppEapError) {
g_peer.log_error(*ppEapError); g_peer.log_error(*ppEapError);

View File

@ -738,13 +738,14 @@ namespace eap
/// - \c false otherwise. See \p ppEapError for details. /// - \c false otherwise. See \p ppEapError for details.
/// ///
virtual bool get_identity( virtual bool get_identity(
_In_ DWORD dwFlags, _In_ DWORD dwFlags,
_In_ const config_providers &cfg, _In_ const config_providers &cfg,
_Inout_ credentials_type &cred, _In_opt_ const credentials_type *cred_in,
_In_ HANDLE hTokenImpersonateUser, _Inout_ credentials_type &cred_out,
_Out_ BOOL *pfInvokeUI, _In_ HANDLE hTokenImpersonateUser,
_Out_ WCHAR **ppwszIdentity, _Out_ BOOL *pfInvokeUI,
_Out_ EAP_ERROR **ppEapError) = 0; _Out_ WCHAR **ppwszIdentity,
_Out_ EAP_ERROR **ppEapError) = 0;
/// ///
/// Defines the implementation of an EAP method-specific function that retrieves the properties of an EAP method given the connection and user data. /// Defines the implementation of an EAP method-specific function that retrieves the properties of an EAP method given the connection and user data.

Binary file not shown.

View File

@ -75,13 +75,14 @@ namespace eap
/// - \c false otherwise. See \p ppEapError for details. /// - \c false otherwise. See \p ppEapError for details.
/// ///
virtual bool get_identity( virtual bool get_identity(
_In_ DWORD dwFlags, _In_ DWORD dwFlags,
_In_ const config_providers &cfg, _In_ const config_providers &cfg,
_Inout_ credentials_type &cred, _In_opt_ const credentials_type *cred_in,
_In_ HANDLE hTokenImpersonateUser, _Inout_ credentials_type &cred_out,
_Out_ BOOL *pfInvokeUI, _In_ HANDLE hTokenImpersonateUser,
_Out_ WCHAR **ppwszIdentity, _Out_ BOOL *pfInvokeUI,
_Out_ EAP_ERROR **ppEapError); _Out_ WCHAR **ppwszIdentity,
_Out_ EAP_ERROR **ppEapError);
/// ///
/// Defines the implementation of an EAP method-specific function that retrieves the properties of an EAP method given the connection and user data. /// Defines the implementation of an EAP method-specific function that retrieves the properties of an EAP method given the connection and user data.

View File

@ -59,13 +59,14 @@ bool eap::peer_ttls::shutdown(_Out_ EAP_ERROR **ppEapError)
bool eap::peer_ttls::get_identity( bool eap::peer_ttls::get_identity(
_In_ DWORD dwFlags, _In_ DWORD dwFlags,
_In_ const config_providers &cfg, _In_ const config_providers &cfg,
_Inout_ credentials_type &cred, _In_opt_ const credentials_type *cred_in,
_In_ HANDLE hTokenImpersonateUser, _Inout_ credentials_type &cred_out,
_Out_ BOOL *pfInvokeUI, _In_ HANDLE hTokenImpersonateUser,
_Out_ WCHAR **ppwszIdentity, _Out_ BOOL *pfInvokeUI,
_Out_ EAP_ERROR **ppEapError) _Out_ WCHAR **ppwszIdentity,
_Out_ EAP_ERROR **ppEapError)
{ {
assert(pfInvokeUI); assert(pfInvokeUI);
assert(ppwszIdentity); assert(ppwszIdentity);
@ -79,56 +80,55 @@ bool eap::peer_ttls::get_identity(
const config_provider &cfg_prov(cfg.m_providers.front()); const config_provider &cfg_prov(cfg.m_providers.front());
const config_method_ttls *cfg_method = dynamic_cast<const config_method_ttls*>(cfg_prov.m_methods.front().get()); const config_method_ttls *cfg_method = dynamic_cast<const config_method_ttls*>(cfg_prov.m_methods.front().get());
bool outer_set = false; bool is_outer_set = false;
assert(cfg_method); assert(cfg_method);
if (cfg_method->m_preshared) { if (cfg_method->m_preshared) {
// Outer TLS identity: Preshared credentials. // Outer TLS: Preshared credentials.
(credentials_tls&)cred = (credentials_tls&)*cfg_method->m_preshared; (credentials_tls&)cred_out = (credentials_tls&)*cfg_method->m_preshared;
log_event(&EAPMETHOD_TRACE_EVT_CRED_PRESHARED, event_data(cred.credentials_tls::target_suffix()), event_data(cred.credentials_tls::get_name()), event_data::blank); log_event(&EAPMETHOD_TRACE_EVT_CRED_PRESHARED, event_data(cred_out.credentials_tls::target_suffix()), event_data(cred_out.credentials_tls::get_name()), event_data::blank);
outer_set = true; is_outer_set = true;
} }
bool inner_set = false; bool is_inner_set = false;
const config_method_pap *cfg_inner_pap = dynamic_cast<const config_method_pap*>(cfg_method->m_inner.get()); const config_method_pap *cfg_inner_pap = dynamic_cast<const config_method_pap*>(cfg_method->m_inner.get());
if (cfg_inner_pap) { if (cfg_inner_pap) {
if (cfg_inner_pap->m_preshared) { if (cfg_inner_pap->m_preshared) {
// Inner PAP identity: Preshared credentials. // Inner PAP: Preshared credentials.
cred.m_inner.reset((credentials*)cfg_inner_pap->m_preshared->clone()); cred_out.m_inner.reset((credentials*)cfg_inner_pap->m_preshared->clone());
log_event(&EAPMETHOD_TRACE_EVT_CRED_PRESHARED, event_data(cred.m_inner->target_suffix()), event_data(cred.m_inner->get_name()), event_data::blank); log_event(&EAPMETHOD_TRACE_EVT_CRED_PRESHARED, event_data(cred_out.m_inner->target_suffix()), event_data(cred_out.m_inner->get_name()), event_data::blank);
inner_set = true; is_inner_set = true;
} }
} else } else
assert(0); // Unsupported inner authentication method type. assert(0); // Unsupported inner authentication method type.
if ((dwFlags & EAP_FLAG_GUEST_ACCESS) == 0 && (!outer_set || !inner_set)) { if ((dwFlags & EAP_FLAG_GUEST_ACCESS) == 0 && (!is_outer_set || !is_inner_set)) {
// Not a guest && some credentials may be missing: Try to load credentials from Windows Credential Manager. // Not a guest && some credentials may be missing: Try to load credentials from Windows Credential Manager.
// Change user context. When applicable. // Change user context. When applicable.
bool user_ctx_changed = hTokenImpersonateUser && ImpersonateLoggedOnUser(hTokenImpersonateUser); bool user_ctx_changed = hTokenImpersonateUser && ImpersonateLoggedOnUser(hTokenImpersonateUser);
if (!outer_set) { if (!is_outer_set) {
if (cred.credentials_tls::retrieve(cfg_prov.m_id.c_str(), ppEapError)) { credentials_tls cred_loaded(*this);
// Outer TLS identity: Stored credentials. if (cred_loaded.retrieve(cfg_prov.m_id.c_str(), ppEapError)) {
log_event(&EAPMETHOD_TRACE_EVT_CRED_STORED, event_data(cred.credentials_tls::target_suffix()), event_data(cred.credentials_tls::get_name()), event_data::blank); // Outer TLS: Stored credentials.
outer_set = true; (credentials_tls&&)cred_out = std::move(cred_loaded);
log_event(&EAPMETHOD_TRACE_EVT_CRED_STORED, event_data(cred_out.credentials_tls::target_suffix()), event_data(cred_out.credentials_tls::get_name()), event_data::blank);
is_outer_set = true;
} else { } else {
// Not actually an error. // Not actually an error.
free_error_memory(*ppEapError); free_error_memory(*ppEapError);
} }
} }
if (!inner_set) { if (!is_inner_set) {
unique_ptr<credentials> cred_loaded; unique_ptr<credentials> cred_loaded;
if (cfg_inner_pap) if (cfg_inner_pap) cred_loaded.reset(new credentials_pap(*this));
cred_loaded.reset(new credentials_pap(*this)); else assert(0); // Unsupported inner authentication method type.
else
assert(0); // Unsupported inner authentication method type.
if (cred_loaded->retrieve(cfg_prov.m_id.c_str(), ppEapError)) { if (cred_loaded->retrieve(cfg_prov.m_id.c_str(), ppEapError)) {
// Inner PAP identity: Stored credentials. // Inner PAP: Stored credentials.
cred.m_inner = std::move(cred_loaded); cred_out.m_inner = std::move(cred_loaded);
log_event(&EAPMETHOD_TRACE_EVT_CRED_STORED, event_data(cred.m_inner->target_suffix()), event_data(cred.m_inner->get_name()), event_data::blank); log_event(&EAPMETHOD_TRACE_EVT_CRED_STORED, event_data(cred_out.m_inner->target_suffix()), event_data(cred_out.m_inner->get_name()), event_data::blank);
inner_set = true; is_inner_set = true;
} else { } else {
// Not actually an error. // Not actually an error.
free_error_memory(*ppEapError); free_error_memory(*ppEapError);
@ -139,32 +139,41 @@ bool eap::peer_ttls::get_identity(
if (user_ctx_changed) RevertToSelf(); if (user_ctx_changed) RevertToSelf();
} }
// Test if we have credentials available anyway (from before - EAP can cache them). if (cred_in) {
// Try cached credentials.
// Note: Outer TLS credentials can be empty! if (!is_outer_set) {
//if (!cred.credentials_tls::empty()) // Outer TLS: EAP service cached credentials.
// outer_set = true; (credentials_tls&)cred_out = (const credentials_tls&)cred_in;
log_event(&EAPMETHOD_TRACE_EVT_CRED_CACHED, event_data(cred_out.credentials_tls::target_suffix()), event_data(cred_out.credentials_tls::get_name()), event_data::blank);
is_outer_set = true;
}
if (cred.m_inner && !cred.m_inner->empty()) if (!is_inner_set && cred_in->m_inner) {
inner_set = true; // Inner PAP: EAP service cached credentials.
cred_out.m_inner.reset((credentials*)cred_in->m_inner->clone());
log_event(&EAPMETHOD_TRACE_EVT_CRED_CACHED, event_data(cred_out.m_inner->target_suffix()), event_data(cred_out.m_inner->get_name()), event_data::blank);
is_inner_set = true;
}
}
*pfInvokeUI = FALSE; *pfInvokeUI = FALSE;
if ((dwFlags & EAP_FLAG_MACHINE_AUTH) == 0) { if ((dwFlags & EAP_FLAG_MACHINE_AUTH) == 0) {
// Per-user authentication // Per-user authentication
if (!outer_set) { if (!is_outer_set) {
log_event(&EAPMETHOD_TRACE_EVT_CRED_INVOKE_UI, event_data(cred.credentials_tls::target_suffix()), event_data::blank); log_event(&EAPMETHOD_TRACE_EVT_CRED_INVOKE_UI, event_data(cred_out.credentials_tls::target_suffix()), event_data::blank);
*pfInvokeUI = TRUE; *pfInvokeUI = TRUE;
return true; return true;
} }
if (!inner_set) { if (!is_inner_set) {
log_event(&EAPMETHOD_TRACE_EVT_CRED_INVOKE_UI, event_data(cred.m_inner->target_suffix()), event_data::blank); log_event(&EAPMETHOD_TRACE_EVT_CRED_INVOKE_UI, event_data(cred_out.m_inner->target_suffix()), event_data::blank);
*pfInvokeUI = TRUE; *pfInvokeUI = TRUE;
return true; return true;
} }
} else { } else {
// Per-machine authentication // Per-machine authentication
if (!outer_set || !inner_set) { if (!is_outer_set || !is_inner_set) {
*ppEapError = make_error(ERROR_NO_SUCH_USER, _T(__FUNCTION__) _T(" Credentials for per-machine authentication not available.")); *ppEapError = make_error(ERROR_NO_SUCH_USER, _T(__FUNCTION__) _T(" Credentials for per-machine authentication not available."));
return false; return false;
} }
@ -176,10 +185,10 @@ bool eap::peer_ttls::get_identity(
wstring identity; wstring identity;
if (cfg_method->m_anonymous_identity.empty()) { if (cfg_method->m_anonymous_identity.empty()) {
// Use the true identity. Outer has the right-of-way. // Use the true identity. Outer has the right-of-way.
identity = std::move(cred.get_identity()); identity = std::move(cred_out.get_identity());
} else if (cfg_method->m_anonymous_identity.compare(L"@") == 0) { } else if (cfg_method->m_anonymous_identity.compare(L"@") == 0) {
// Strip username part from identity (RFC 4822). // Strip username part from identity (RFC 4822).
identity = std::move(cred.get_identity()); identity = std::move(cred_out.get_identity());
wstring::size_type offset = identity.find(L'@'); wstring::size_type offset = identity.find(L'@');
if (offset != wstring::npos) identity.erase(0, offset); if (offset != wstring::npos) identity.erase(0, offset);
} else { } else {