method_eap: Support EAP identity exchange

Although, EapHost takes care for EAP identity exchange for us, it does
so for the outer-most method only. When using EAP inside a TLS tunnel,
we are responsible for EAP identity exchange ourselves.

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
2020-01-20 13:18:21 +01:00
parent 1c295360fc
commit e5e5f1c63e
3 changed files with 59 additions and 25 deletions

View File

@@ -121,7 +121,7 @@ void eap::peer_ttls::get_identity(
} else {
// Per-machine authentication, cannot use UI.
throw win_runtime_error(ERROR_NO_SUCH_USER, __FUNCTION__ " Credentials for per-machine authentication not available.");
}
}
}
// Build our identity. ;)
@@ -138,7 +138,7 @@ void eap::peer_ttls::get_identity(
void eap::peer_ttls::get_method_properties(
_In_ DWORD dwVersion,
_In_ DWORD dwFlags,
_In_ DWORD dwFlags,
_In_ HANDLE hUserImpersonationToken,
_In_count_(dwConnectionDataSize) const BYTE *pConnectionData,
_In_ DWORD dwConnectionDataSize,
@@ -259,11 +259,11 @@ EAP_SESSION_HANDLE eap::peer_ttls::begin_session(
case eap_type_t::legacy_mschapv2: meth_inner.reset(new method_mschapv2_diameter(*this, dynamic_cast<config_method_mschapv2&>(*cfg_inner), dynamic_cast<credentials_pass&>(*cred_inner))); break;
case eap_type_t::mschapv2 : meth_inner.reset(
new method_eapmsg (*this, cred_inner->get_identity().c_str(),
new method_eap (*this, eap_type_t::mschapv2,
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))))); break;
case eap_type_t::gtc : meth_inner.reset(
new method_eapmsg (*this, cred_inner->get_identity().c_str(),
new method_eap (*this, eap_type_t::gtc,
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))))); break;
default: throw invalid_argument(__FUNCTION__ " Unsupported inner authentication method.");
}
@@ -277,7 +277,7 @@ EAP_SESSION_HANDLE eap::peer_ttls::begin_session(
}
#endif
s->m_method.reset(
new method_eap (*this, eap_type_t::ttls,
new method_eap (*this, eap_type_t::ttls, *s->m_cred.m_cred,
new method_defrag(*this, 0, /* Schannel supports retrieving keying material for EAP-TTLSv0 only. */
new method_ttls (*this, *cfg_method, *dynamic_cast<credentials_ttls*>(s->m_cred.m_cred.get()), meth_inner.release()))));
@@ -596,7 +596,7 @@ DWORD WINAPI eap::peer_ttls::crl_checker::verify(_In_ crl_checker *obj)
if (WaitForSingleObject(obj->m_abort, 5000) == WAIT_OBJECT_0) {
// Aborted.
return 1;
}
}
// Prepare a list of certificates forming certificate chain.
list<cert_context> context_data;
@@ -605,7 +605,7 @@ DWORD WINAPI eap::peer_ttls::crl_checker::verify(_In_ crl_checker *obj)
DWORD flags = 0;
c = CertGetIssuerCertificateFromStore(obj->m_cert->hCertStore, context_data.back(), NULL, &flags);
if (!c) break;
}
}
// Create an array of pointers to CERT_CONTEXT required by CertVerifyRevocation().
vector<PCERT_CONTEXT> context;
@@ -623,7 +623,7 @@ DWORD WINAPI eap::peer_ttls::crl_checker::verify(_In_ crl_checker *obj)
if (!CertVerifyRevocation(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
(DWORD)(c_end - c), reinterpret_cast<PVOID*>(&*c),
CERT_VERIFY_REV_CHAIN_FLAG, NULL, &status_rev))
{
{
PCCERT_CONTEXT cert = *(c + status_rev.dwIndex);
wstring subj;
if (!CertGetNameStringW(cert, CERT_NAME_DNS_TYPE, CERT_NAME_STR_ENABLE_PUNYCODE_FLAG, NULL, subj))
@@ -639,7 +639,7 @@ DWORD WINAPI eap::peer_ttls::crl_checker::verify(_In_ crl_checker *obj)
// This really was an error, as it appeared before the root CA cerficate in the chain.
obj->m_module.log_event(&EAPMETHOD_TLS_SERVER_CERT_REVOKE_SKIPPED, event_data((unsigned int)eap_type_t::ttls), event_data(subj), event_data::blank);
}
break;
break;
case CRYPT_E_REVOKED:
// One of the certificates in the chain was revoked.
@@ -650,7 +650,7 @@ DWORD WINAPI eap::peer_ttls::crl_checker::verify(_In_ crl_checker *obj)
case CRL_REASON_CERTIFICATE_HOLD:
// The revocation was of administrative nature. No need to black-list.
obj->m_module.log_event(&EAPMETHOD_TLS_SERVER_CERT_REVOKED1, event_data((unsigned int)eap_type_t::ttls), event_data(subj), event_data(status_rev.dwReason), event_data::blank);
break;
break;
default: {
// One of the certificates in the chain was revoked as compromised. Black-list it.
@@ -669,18 +669,18 @@ DWORD WINAPI eap::peer_ttls::crl_checker::verify(_In_ crl_checker *obj)
// Resume checking the rest of the chain.
c += (size_t)status_rev.dwIndex + 1;
break;
break;
case ERROR_SUCCESS:
// Odd. CertVerifyRevocation() should return TRUE then. Nevertheless, we take this as a "yes".
c = c_end;
break;
break;
default:
default:
// Checking one of the certificates in the chain for revocation failed. Resume checking the rest.
obj->m_module.log_event(&EAPMETHOD_TLS_SERVER_CERT_REVOKE_FAILED, event_data((unsigned int)eap_type_t::ttls), event_data(subj), event_data(status_rev.dwError), event_data::blank);
c += (size_t)status_rev.dwIndex + 1;
}
}
} else {
// Revocation check finished.
break;