Credentials are no longer stored using method name (TLS/PAP/MSCHAPv2) but with level/type identifier
This commit is contained in:
@@ -205,9 +205,10 @@ namespace eap
|
||||
///
|
||||
/// Constructs configuration
|
||||
///
|
||||
/// \param[in] mod EAP module to use for global services
|
||||
/// \param[in] mod EAP module to use for global services
|
||||
/// \param[in] level Config level (0=outer, 1=inner, 2=inner-inner...)
|
||||
///
|
||||
config_method(_In_ module &mod);
|
||||
config_method(_In_ module &mod, _In_ unsigned int level);
|
||||
|
||||
///
|
||||
/// Copies configuration
|
||||
@@ -252,6 +253,9 @@ namespace eap
|
||||
/// Returns a string identifier of the EAP method type of this configuration
|
||||
///
|
||||
virtual const wchar_t* get_method_str() const = 0;
|
||||
|
||||
public:
|
||||
const unsigned int m_level; ///< Config level (0=outer, 1=inner, 2=inner-inner...)
|
||||
};
|
||||
|
||||
|
||||
@@ -264,9 +268,10 @@ namespace eap
|
||||
///
|
||||
/// Constructs configuration
|
||||
///
|
||||
/// \param[in] mod EAP module to use for global services
|
||||
/// \param[in] mod EAP module to use for global services
|
||||
/// \param[in] level Config level (0=outer, 1=inner, 2=inner-inner...)
|
||||
///
|
||||
config_method_with_cred(_In_ module &mod);
|
||||
config_method_with_cred(_In_ module &mod, _In_ unsigned int level);
|
||||
|
||||
///
|
||||
/// Copies configuration
|
||||
|
@@ -179,28 +179,40 @@ namespace eap
|
||||
/// Save credentials to Windows Credential Manager
|
||||
///
|
||||
/// \param[in] pszTargetName The name in Windows Credential Manager to store credentials as
|
||||
/// \param[in] level Credential level (0=outer, 1=inner, 2=inner-inner...)
|
||||
///
|
||||
virtual void store(_In_z_ LPCTSTR pszTargetName) const = 0;
|
||||
virtual void store(_In_z_ LPCTSTR pszTargetName, _In_ unsigned int level) const = 0;
|
||||
|
||||
///
|
||||
/// Retrieve credentials from Windows Credential Manager
|
||||
///
|
||||
/// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from
|
||||
/// \param[in] level Credential level (0=outer, 1=inner, 2=inner-inner...)
|
||||
///
|
||||
virtual void retrieve(_In_z_ LPCTSTR pszTargetName) = 0;
|
||||
virtual void retrieve(_In_z_ LPCTSTR pszTargetName, _In_ unsigned int level) = 0;
|
||||
|
||||
///
|
||||
/// Returns target name for Windows Credential Manager credential name
|
||||
///
|
||||
/// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from
|
||||
/// \param[in] level Credential level (0=outer, 1=inner, 2=inner-inner...)
|
||||
///
|
||||
/// \returns Final target name to store/retrieve credentials in Windows Credential Manager
|
||||
///
|
||||
inline winstd::tstring target_name(_In_z_ LPCTSTR pszTargetName) const
|
||||
inline winstd::tstring target_name(_In_z_ LPCTSTR pszTargetName, _In_ unsigned int level) const
|
||||
{
|
||||
// Start with product name and given target name (identity provider usually).
|
||||
winstd::tstring target_name(_T(PRODUCT_NAME_STR) _T("/"));
|
||||
target_name += pszTargetName;
|
||||
target_name += _T('/');
|
||||
|
||||
// Append level of credentials.
|
||||
TCHAR buf[20];
|
||||
_ultot_s(level, buf, _countof(buf), 10);
|
||||
target_name += buf;
|
||||
target_name += _T('/');
|
||||
|
||||
// Append credential type.
|
||||
target_name += target_suffix();
|
||||
assert(target_name.length() < CRED_MAX_GENERIC_TARGET_NAME_LENGTH);
|
||||
return target_name;
|
||||
@@ -291,6 +303,13 @@ namespace eap
|
||||
///
|
||||
credentials_pass& operator=(_Inout_ credentials_pass &&other);
|
||||
|
||||
///
|
||||
/// Clones credentials
|
||||
///
|
||||
/// \returns Pointer to cloned credentials
|
||||
///
|
||||
virtual config* clone() const;
|
||||
|
||||
///
|
||||
/// Resets credentials
|
||||
///
|
||||
@@ -358,18 +377,46 @@ namespace eap
|
||||
/// Save credentials to Windows Credential Manager
|
||||
///
|
||||
/// \param[in] pszTargetName The name in Windows Credential Manager to store credentials as
|
||||
/// \param[in] level Credential level (0=outer, 1=inner, 2=inner-inner...)
|
||||
///
|
||||
virtual void store(_In_z_ LPCTSTR pszTargetName) const;
|
||||
virtual void store(_In_z_ LPCTSTR pszTargetName, _In_ unsigned int level) const;
|
||||
|
||||
///
|
||||
/// Retrieve credentials from Windows Credential Manager
|
||||
///
|
||||
/// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from
|
||||
/// \param[in] level Credential level (0=outer, 1=inner, 2=inner-inner...)
|
||||
///
|
||||
virtual void retrieve(_In_z_ LPCTSTR pszTargetName);
|
||||
virtual void retrieve(_In_z_ LPCTSTR pszTargetName, _In_ unsigned int level);
|
||||
|
||||
///
|
||||
/// Return target suffix for Windows Credential Manager credential name
|
||||
///
|
||||
virtual LPCTSTR target_suffix() const;
|
||||
|
||||
/// @}
|
||||
|
||||
///
|
||||
/// Combine credentials in the following order:
|
||||
///
|
||||
/// 1. Cached credentials
|
||||
/// 2. Pre-configured credentials
|
||||
/// 3. Stored credentials
|
||||
///
|
||||
/// \param[in] cred_cached Cached credentials (optional, can be \c NULL, must be credentials_pass* type)
|
||||
/// \param[in] cfg Method configuration (must be config_method_pap type)
|
||||
/// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL)
|
||||
///
|
||||
/// \returns
|
||||
/// - \c source_cache Credentials were obtained from EapHost cache
|
||||
/// - \c source_preshared Credentials were set by method configuration
|
||||
/// - \c source_storage Credentials were loaded from Windows Credential Manager
|
||||
///
|
||||
virtual source_t combine(
|
||||
_In_ const credentials *cred_cached,
|
||||
_In_ const config_method_with_cred &cfg,
|
||||
_In_opt_z_ LPCTSTR pszTargetName);
|
||||
|
||||
public:
|
||||
winstd::sanitizing_wstring m_password; ///< Password
|
||||
|
||||
|
@@ -102,25 +102,33 @@ const bstr eap::config::namespace_eapmetadata(L"urn:ietf:params:xml:ns:yang:ietf
|
||||
// eap::config_method
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::config_method::config_method(_In_ module &mod) : config(mod)
|
||||
eap::config_method::config_method(_In_ module &mod, _In_ unsigned int level) :
|
||||
m_level(level),
|
||||
config(mod)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config_method::config_method(_In_ const config_method &other) : config(other)
|
||||
eap::config_method::config_method(_In_ const config_method &other) :
|
||||
m_level(other.m_level),
|
||||
config(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config_method::config_method(_Inout_ config_method &&other) : config(std::move(other))
|
||||
eap::config_method::config_method(_Inout_ config_method &&other) :
|
||||
m_level(other.m_level),
|
||||
config(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config_method& eap::config_method::operator=(_In_ const config_method &other)
|
||||
{
|
||||
if (this != &other)
|
||||
if (this != &other) {
|
||||
assert(m_level == other.m_level); // Allow copy within same configuration level only.
|
||||
(config&)*this = other;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -128,8 +136,10 @@ eap::config_method& eap::config_method::operator=(_In_ const config_method &othe
|
||||
|
||||
eap::config_method& eap::config_method::operator=(_Inout_ config_method &&other)
|
||||
{
|
||||
if (this != &other)
|
||||
if (this != &other) {
|
||||
assert(m_level == other.m_level); // Allow move within same configuration level only.
|
||||
(config&&)*this = std::move(other);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -139,11 +149,11 @@ eap::config_method& eap::config_method::operator=(_Inout_ config_method &&other)
|
||||
// eap::config_method_with_cred
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::config_method_with_cred::config_method_with_cred(_In_ module &mod) :
|
||||
eap::config_method_with_cred::config_method_with_cred(_In_ module &mod, _In_ unsigned int level) :
|
||||
m_allow_save(true),
|
||||
m_use_preshared(false),
|
||||
m_last_status(status_success),
|
||||
config_method(mod)
|
||||
config_method(mod, level)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -197,6 +197,12 @@ eap::credentials_pass& eap::credentials_pass::operator=(_Inout_ credentials_pass
|
||||
}
|
||||
|
||||
|
||||
eap::config* eap::credentials_pass::clone() const
|
||||
{
|
||||
return new credentials_pass(*this);
|
||||
}
|
||||
|
||||
|
||||
void eap::credentials_pass::clear()
|
||||
{
|
||||
credentials::clear();
|
||||
@@ -275,7 +281,7 @@ void eap::credentials_pass::operator>>(_Inout_ cursor_in &cursor)
|
||||
}
|
||||
|
||||
|
||||
void eap::credentials_pass::store(_In_z_ LPCTSTR pszTargetName) const
|
||||
void eap::credentials_pass::store(_In_z_ LPCTSTR pszTargetName, _In_ unsigned int level) const
|
||||
{
|
||||
assert(pszTargetName);
|
||||
|
||||
@@ -290,7 +296,7 @@ void eap::credentials_pass::store(_In_z_ LPCTSTR pszTargetName) const
|
||||
if (!CryptProtectData(&cred_blob, NULL, &entropy_blob, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &cred_enc))
|
||||
throw win_runtime_error(__FUNCTION__ " CryptProtectData failed.");
|
||||
|
||||
tstring target(target_name(pszTargetName));
|
||||
tstring target(target_name(pszTargetName, level));
|
||||
|
||||
// Write credentials.
|
||||
assert(cred_enc.cbData < CRED_MAX_CREDENTIAL_BLOB_SIZE);
|
||||
@@ -314,13 +320,13 @@ void eap::credentials_pass::store(_In_z_ LPCTSTR pszTargetName) const
|
||||
}
|
||||
|
||||
|
||||
void eap::credentials_pass::retrieve(_In_z_ LPCTSTR pszTargetName)
|
||||
void eap::credentials_pass::retrieve(_In_z_ LPCTSTR pszTargetName, _In_ unsigned int level)
|
||||
{
|
||||
assert(pszTargetName);
|
||||
|
||||
// Read credentials.
|
||||
unique_ptr<CREDENTIAL, CredFree_delete<CREDENTIAL> > cred;
|
||||
if (!CredRead(target_name(pszTargetName).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred))
|
||||
if (!CredRead(target_name(pszTargetName, level).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred))
|
||||
throw win_runtime_error(__FUNCTION__ " CredRead failed.");
|
||||
|
||||
// Decrypt the password using user's key.
|
||||
@@ -351,6 +357,49 @@ void eap::credentials_pass::retrieve(_In_z_ LPCTSTR pszTargetName)
|
||||
}
|
||||
|
||||
|
||||
LPCTSTR eap::credentials_pass::target_suffix() const
|
||||
{
|
||||
return _T("pass");
|
||||
}
|
||||
|
||||
|
||||
eap::credentials::source_t eap::credentials_pass::combine(
|
||||
_In_ const credentials *cred_cached,
|
||||
_In_ const config_method_with_cred &cfg,
|
||||
_In_opt_z_ LPCTSTR pszTargetName)
|
||||
{
|
||||
if (cred_cached) {
|
||||
// Using EAP service cached credentials.
|
||||
*this = *(credentials_pass*)cred_cached;
|
||||
m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_CACHED1, event_data((unsigned int)cfg.get_method_id()), event_data(credentials_pass::get_name()), event_data::blank);
|
||||
return source_cache;
|
||||
}
|
||||
|
||||
if (cfg.m_use_preshared) {
|
||||
// Using preshared credentials.
|
||||
*this = *(credentials_pass*)cfg.m_preshared.get();
|
||||
m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_PRESHARED1, event_data((unsigned int)cfg.get_method_id()), event_data(credentials_pass::get_name()), event_data::blank);
|
||||
return source_preshared;
|
||||
}
|
||||
|
||||
if (pszTargetName) {
|
||||
try {
|
||||
credentials_pass cred_loaded(m_module);
|
||||
cred_loaded.retrieve(pszTargetName, cfg.m_level);
|
||||
|
||||
// Using stored credentials.
|
||||
*this = std::move(cred_loaded);
|
||||
m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_STORED1, event_data((unsigned int)cfg.get_method_id()), event_data(credentials_pass::get_name()), event_data::blank);
|
||||
return source_storage;
|
||||
} catch (...) {
|
||||
// Not actually an error.
|
||||
}
|
||||
}
|
||||
|
||||
return source_unknown;
|
||||
}
|
||||
|
||||
|
||||
const unsigned char eap::credentials_pass::s_entropy[1024] = {
|
||||
0x40, 0x88, 0xd3, 0x13, 0x81, 0x8a, 0xf6, 0x74, 0x55, 0x8e, 0xcc, 0x73, 0x2c, 0xf8, 0x93, 0x37,
|
||||
0x4f, 0xeb, 0x1d, 0x66, 0xb7, 0xfb, 0x47, 0x75, 0xb4, 0xfd, 0x07, 0xbb, 0xf6, 0xb3, 0x05, 0x30,
|
||||
|
Reference in New Issue
Block a user