VBoxCredProvCredential.cpp revision 4ddd24feeef95a6bb2f72fba69fe3bc9630409fa
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync * VBoxCredProvCredential - Class for keeping and handling the passed credentials.
3f1e0eea71cabeb90529e546f16eb7aee513fde9vboxsync * Copyright (C) 2012 Oracle Corporation
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Header Files *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsyncVBoxCredProvCredential::VBoxCredProvCredential(void) :
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential: Created\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RT_BZERO(m_apwszCredentials, sizeof(PRTUTF16) * VBOXCREDPROV_NUM_FIELDS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVBoxCredProvCredential::~VBoxCredProvCredential(void)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential: Destroying\n");
d03c6bcd3d78cef8ac4d76186e7c0e72f63ce80fvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::AddRef: Returning refcount=%ld\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::Release: Returning refcount=%ld\n",
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential: Calling destructor\n");
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync delete this;
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsyncVBoxCredProvCredential::QueryInterface(REFIID interfaceID, void **ppvInterface)
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync || IID_ICredentialProviderCredential == interfaceID)
683371bbf37760161d1b8454ce978acf89bbb04fvboxsync reinterpret_cast<IUnknown*>(*ppvInterface)->AddRef();
ad9297dbc9565afa293c95d8a3eb2cc4bbaffe27vboxsync * Assigns or copies a RTUTF16 string to a UNICODE_STRING.
ad9297dbc9565afa293c95d8a3eb2cc4bbaffe27vboxsync * When fCopy is false, this does *not* copy its contents
ad9297dbc9565afa293c95d8a3eb2cc4bbaffe27vboxsync * and only assigns its code points to the destination!
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * When fCopy is true, the actual string buffer gets copied.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * Does not take terminating \0 into account.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * @return HRESULT
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * @param pUnicodeDest Unicode string assigning the UTF16 string to.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * @param pwszSource UTF16 string to assign.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * @param fCopy Whether to just assign or copy the actual buffer
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * contents from source -> dest.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * @todo r=bird: It appears that fCopy == true is never used, which is
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * fortunate as it (a) doesn't check for there being room in the
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * buffer, (b) terminate the string (which is customary, even if not
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * strictly necessary), and (c) overwrites MaximumLength.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsyncVBoxCredProvCredential::RTUTF16ToUnicode(PUNICODE_STRING pUnicodeDest, PRTUTF16 pwszSource, bool fCopy)
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync size_t cbLen = RTUtf16Len(pwszSource) * sizeof(RTUTF16);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync else /* Just assign the buffer. */
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsyncVBoxCredProvCredential::AllocateLogonPackage(const KERB_INTERACTIVE_UNLOCK_LOGON &rUnlockLogon, PBYTE *ppPackage, DWORD *pcbPackage)
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync const KERB_INTERACTIVE_LOGON *pLogonIn = &rUnlockLogon.Logon;
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * First, allocate enough space for the logon structure itself and separate
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * string buffers right after it to store the actual user, password and domain
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * credentials.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync DWORD cbLogon = sizeof(KERB_INTERACTIVE_UNLOCK_LOGON)
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvVerbose(3, "VBoxCredProvCredential::AllocateLogonPackage: Allocating %ld bytes (%d bytes credentials)\n",
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync cbLogon, cbLogon - sizeof(KERB_INTERACTIVE_UNLOCK_LOGON));
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync KERB_INTERACTIVE_UNLOCK_LOGON *pLogon = (KERB_INTERACTIVE_UNLOCK_LOGON*)CoTaskMemAlloc(cbLogon);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync /* Let our byte buffer point to the end of our allocated structure so that it can
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * be used to store the credential data sequentially in a binary blob
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * (without terminating \0). */
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync PBYTE pbBuffer = (PBYTE)pLogon + sizeof(KERB_INTERACTIVE_UNLOCK_LOGON);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync /* The buffer of the packed destination string does not contain the actual
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * string content but a relative offset starting at the given
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * KERB_INTERACTIVE_UNLOCK_LOGON structure. */
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync#define KERB_CRED_INIT_PACKED(StringDst, StringSrc, LogonOffset) \
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync memcpy(StringDst.Buffer, StringSrc.Buffer, StringDst.Length); \
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync StringDst.Buffer = (PWSTR)(pbBuffer - (PBYTE)LogonOffset); \
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync KERB_INTERACTIVE_LOGON *pLogonOut = &pLogon->Logon;
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync KERB_CRED_INIT_PACKED(pLogonOut->LogonDomainName, pLogonIn->LogonDomainName, pLogon);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync KERB_CRED_INIT_PACKED(pLogonOut->UserName , pLogonIn->UserName, pLogon);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync KERB_CRED_INIT_PACKED(pLogonOut->Password , pLogonIn->Password, pLogon);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * Resets (wipes) stored credentials.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * @return HRESULT
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::Reset: Wiping credentials user=%ls, pw=%ls, domain=%ls\n",
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync L"XXX" /* Don't show any passwords in release mode. */,
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VbglR3CredentialsDestroyUtf16(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME],
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME],
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync /* Note: On Windows 8, set "this" to "nullptr". */
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync HRESULT hr2 = m_pEvents->SetFieldString(this, VBOXCREDPROV_FIELDID_USERNAME, L"");
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync hr2 = m_pEvents->SetFieldString(this, VBOXCREDPROV_FIELDID_PASSWORD, L"");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr2 = m_pEvents->SetFieldString(this, VBOXCREDPROV_FIELDID_DOMAINNAME, L"");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::Reset: Returned hr=%08x\n", hr);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * Checks and retrieves credentials provided by the host + does account lookup on eventually
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync * renamed user accounts.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * @return IPRT status code.
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync * Set status to "terminating" to let the host know this module now
3242fe628b2306c050fb28c489d50bc63118f0c5vboxsync * tries to receive and use passed credentials so that credentials from
3242fe628b2306c050fb28c489d50bc63118f0c5vboxsync * the host won't be sent twice.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Terminating);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync rc = VbglR3CredentialsRetrieveUtf16(&m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME],
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync &m_apwszCredentials[VBOXCREDPROV_FIELDID_PASSWORD],
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync &m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Retrieved credentials with rc=%Rrc\n", rc);
648b0a0e189323afe4d836f1848f82c7dded0e58vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: User=%ls, Password=%ls, Domain=%ls\n",
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync L"XXX" /* Don't show any passwords in release mode. */,
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * In case we got a "display name" (e.g. "John Doe")
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * instead of the real user name (e.g. "jdoe") we have
683371bbf37760161d1b8454ce978acf89bbb04fvboxsync * to translate the data first ...
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync if (TranslateAccountName(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], &pwszAcount))
ad9297dbc9565afa293c95d8a3eb2cc4bbaffe27vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Translated account name %ls -> %ls\n",
ad9297dbc9565afa293c95d8a3eb2cc4bbaffe27vboxsync m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], pwszAcount);
ad9297dbc9565afa293c95d8a3eb2cc4bbaffe27vboxsync if (m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME])
ad9297dbc9565afa293c95d8a3eb2cc4bbaffe27vboxsync RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME],
ad9297dbc9565afa293c95d8a3eb2cc4bbaffe27vboxsync RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) + sizeof(RTUTF16),
ad9297dbc9565afa293c95d8a3eb2cc4bbaffe27vboxsync RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]);
ad9297dbc9565afa293c95d8a3eb2cc4bbaffe27vboxsync m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME] = pwszAcount;
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * Okay, no display name, but maybe it's a
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * principal name from which we have to extract the domain from?
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * (jdoe@my-domain.sub.net.com -> jdoe in domain my-domain.sub.net.com.)
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync if (ExtractAccoutData(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME],
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync /* Update user name. */
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync if (m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME])
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME],
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) + sizeof(RTUTF16),
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME] = pwszAcount;
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync /* Update domain. */
648b0a0e189323afe4d836f1848f82c7dded0e58vboxsync if (m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME])
648b0a0e189323afe4d836f1848f82c7dded0e58vboxsync RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME],
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]) + sizeof(RTUTF16),
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME] = pwszDomain;
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Extracted account data pwszAccount=%ls, pwszDomain=%ls\n",
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync /* If credentials already were retrieved by a former call, don't try to retrieve new ones
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * and just report back the already retrieved ones. */
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Credentials already retrieved\n");
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Returned rc=%Rrc\n", rc);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * Initializes this credential with the current credential provider
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * usage scenario.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsyncVBoxCredProvCredential::Initialize(CREDENTIAL_PROVIDER_USAGE_SCENARIO enmUsageScenario)
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::Initialize: enmUsageScenario=%ld\n", enmUsageScenario);
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * Called by LogonUI when it needs this credential's advice.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * At the moment we only grab the credential provider events so that we can
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * trigger a re-enumeration of the credentials later.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsyncVBoxCredProvCredential::Advise(ICredentialProviderCredentialEvents *pEvents)
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::Advise: pEvents=0x%p\n",
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * Called by LogonUI when it's finished with handling this credential.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * We only need to release the credential provider events, if any.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::UnAdvise\n");
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * Called by LogonUI when a user profile (tile) has been selected.
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * As we don't want Winlogon to try logging in immediately we set pfAutoLogon
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * to FALSE (if set).
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsyncVBoxCredProvCredential::SetSelected(PBOOL pfAutoLogon)
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::SetSelected\n");
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * Don't do auto logon here because it would retry too often with
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * every credential field (user name, password, domain, ...) which makes
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * winlogon wait before new login attempts can be made.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Called by LogonUI when a user profile (tile) has been unselected again.
afa761a969c8883e5ea370e898d40ce053fbcb22vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::SetDeselected\n");
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync m_pEvents->SetFieldString(this, VBOXCREDPROV_FIELDID_PASSWORD, L"");
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync * Called by LogonUI to retrieve the (interactive) state of a UI field.
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsyncVBoxCredProvCredential::GetFieldState(DWORD dwFieldID, CREDENTIAL_PROVIDER_FIELD_STATE *pFieldState,
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE *pFieldstateInteractive)
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::GetFieldState: dwFieldID=%ld\n", dwFieldID);
3242fe628b2306c050fb28c489d50bc63118f0c5vboxsync *pFieldState = s_VBoxCredProvFields[dwFieldID].state;
cea26cf0a0d390c2cca75cb19cb0e86c580e9d77vboxsync *pFieldstateInteractive = s_VBoxCredProvFields[dwFieldID].stateInteractive;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Searches the account name based on a display (real) name (e.g. "John Doe" -> "jdoe").
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Result "ppwszAccoutName" needs to be freed with CoTaskMemFree!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVBoxCredProvCredential::TranslateAccountName(PWSTR pwszDisplayName, PWSTR *ppwszAccoutName)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::TranslateAccountName: Getting account name for \"%ls\" ...\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo Do we need ADS support (e.g. TranslateNameW) here? */
23de3d76e5d27015e334e6ff763ab08de5969363vboxsync BOOL fFound = FALSE; /* Did we find the desired user? */
23de3d76e5d27015e334e6ff763ab08de5969363vboxsync DWORD dwLevel = 2; /* Detailed information about user accounts. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rcStatus = NetUserEnum(NULL, /* Server name, NULL for localhost. */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync * Search for the "display name" - that might be
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * "John Doe" or something similar the user recognizes easier
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync * and may not the same as the "account" name (e.g. "jdoe").
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && StrCmpI(pwszDisplayName, pCurBuf->usri2_full_name) == 0)
61e80138f3c5ea5213990bde94a973c8e64d1dadvboxsync * Copy the real user name (e.g. "jdoe") to our
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * output buffer.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync HRESULT hr = SHStrDupW(pCurBuf->usri2_name, &pwszTemp);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::TranslateAccountName: Error copying data, hr=%08x\n", hr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::TranslateAccountName returned rcStatus=%ld, fFound=%RTbool\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( TranslateNameW(pwszName, NameUnknown, NameUserPrincipal, NULL, &cbLen)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::GetAccountName: Translated ADS name has %u characters\n", cbLen));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ppwszAccoutName = (PWSTR)RTMemAlloc(cbLen * sizeof(WCHAR));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (TranslateNameW(pwszName, NameUnknown, NameUserPrincipal, ppwszAccoutName, &cbLen))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::GetAccountName: Real ADS account name of '%ls' is '%ls'\n",
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync /* The above method for looking up in ADS failed, try another one. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Extracts the actual account name & domain from a (raw) account data string.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * This might be a principal or FQDN string.
090f6abdd6282f48527b83162b8b441425f05e36vboxsyncVBoxCredProvCredential::ExtractAccoutData(PWSTR pwszAccountData, PWSTR *ppwszAccoutName, PWSTR *ppwszDomain)
9371df33e2b99a59304093df9f492440fdbff171vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::ExtractAccoutData: Getting account name for \"%ls\" ...\n",
9371df33e2b99a59304093df9f492440fdbff171vboxsync /* Try to figure out whether this is a principal name (user@domain). */
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync if ( (pPos = StrChrW(pwszAccountData, L'@')) != NULL
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync size_t cbSize = (pPos - pwszAccountData) * sizeof(WCHAR);
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync LPWSTR pwszName = (LPWSTR)CoTaskMemAlloc(cbSize + sizeof(WCHAR)); /* Space for terminating zero. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = StringCbCopyN(pwszName, cbSize + sizeof(WCHAR), pwszAccountData, cbSize);
090f6abdd6282f48527b83162b8b441425f05e36vboxsync *pPos++; /* Skip @, point to domain name (if any). */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::ExtractAccoutData: Error copying domain data, hr=%08x\n", hr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::ExtractAccoutData: No domain name found!\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::ExtractAccoutData: Error copying account data, hr=%08x\n", hr);
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::ExtractAccoutData: No valid principal account name found!\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Returns the value of a specified LogonUI field.
648b0a0e189323afe4d836f1848f82c7dded0e58vboxsync * @return IPRT status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param dwFieldID Field ID to get value for.
0b65654be767b9fb7677181ddb434d8467f608e3vboxsync * @param ppwszString Pointer that receives the actual value of the specified field.
323b78bf4831666c95416edf3b6e54657a769e5dvboxsyncVBoxCredProvCredential::GetStringValue(DWORD dwFieldID, PWSTR *ppwszString)
0ebb1ef53864eb9cc97580f722288c9b29bc5d03vboxsync /* Fill in standard value to make Winlogon happy. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = SHStrDupW(m_apwszCredentials[dwFieldID], ppwszString);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else /* Fill in an empty value. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::GetStringValue: dwFieldID=%ld, ppwszString=%ls\n",
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Returns back the field ID of which the submit button should be put next to.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * We always want to be the password field put next to the submit button
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * currently.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @return HRESULT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param dwFieldID Field ID of the submit button.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pdwAdjacentTo Field ID where to put the submit button next to.
323b78bf4831666c95416edf3b6e54657a769e5dvboxsyncVBoxCredProvCredential::GetSubmitButtonValue(DWORD dwFieldID, DWORD *pdwAdjacentTo)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::GetSubmitButtonValue: dwFieldID=%ld\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Validate parameters. */
dcc035155cdf232a3d79024f475c2d4448981e85vboxsync if ( dwFieldID == VBOXCREDPROV_FIELDID_SUBMIT_BUTTON
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync /* pdwAdjacentTo is a pointer to the fieldID you want the submit button to appear next to. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::GetSubmitButtonValue: dwFieldID=%ld, *pdwAdjacentTo=%ld\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Sets the value of a specified field. Currently not used.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @return HRESULT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param dwFieldID Field to set value for.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pcwzString Actual value to set.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVBoxCredProvCredential::SetStringValue(DWORD dwFieldID, PCWSTR pcwzString)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::SetStringValue: dwFieldID=%ld, pcwzString=%ls\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Do more things here later. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::SetStringValue returned with hr=%08x\n", hr);
f3701698f9d61fed78c320c3b35c64a0c63d6db1vboxsyncVBoxCredProvCredential::GetBitmapValue(DWORD dwFieldID, HBITMAP *phBitmap)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* We don't do own bitmaps. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVBoxCredProvCredential::GetCheckboxValue(DWORD dwFieldID, BOOL *pfChecked, PWSTR *ppwszLabel)
a64bf60e92e5cb8a76aa6c8e92193932d88a906fvboxsyncVBoxCredProvCredential::GetComboBoxValueCount(DWORD dwFieldID, DWORD *pcItems, DWORD *pdwSelectedItem)
323b78bf4831666c95416edf3b6e54657a769e5dvboxsyncVBoxCredProvCredential::GetComboBoxValueAt(DWORD dwFieldID, DWORD dwItem, PWSTR *ppwszItem)
323b78bf4831666c95416edf3b6e54657a769e5dvboxsyncVBoxCredProvCredential::SetCheckboxValue(DWORD dwFieldID, BOOL fChecked)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVBoxCredProvCredential::SetComboBoxSelectedValue(DWORD dwFieldId, DWORD dwSelectedItem)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVBoxCredProvCredential::CommandLinkClicked(DWORD dwFieldID)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Does the actual authentication stuff to attempt a login.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @return HRESULT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pcpGetSerializationResponse Credential serialization response.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pcpCredentialSerialization Details about the current credential.
d45f7f7fe0c28b500b45b2dc88d7a04f4c0be6b8vboxsync * @param ppwszOptionalStatusText Text to set. Optional.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pcpsiOptionalStatusIcon Status icon to set. Optional.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVBoxCredProvCredential::GetSerialization(CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *pcpGetSerializationResponse,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpCredentialSerialization,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync CREDENTIAL_PROVIDER_STATUS_ICON *pcpsiOptionalStatusIcon)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RT_BZERO(&KerberosUnlockLogon, sizeof(KerberosUnlockLogon));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Save a pointer to the interactive logon struct. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync KERB_INTERACTIVE_LOGON *pKerberosLogon = &KerberosUnlockLogon.Logon;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::GetSerialization: Username=%ls, Password=%ls, Domain=%ls\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Do we have a domain name set? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync && RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = RTUTF16ToUnicode(&pKerberosLogon->LogonDomainName,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME],
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync false /* Just assign, no copy */);
f3701698f9d61fed78c320c3b35c64a0c63d6db1vboxsync else /* No domain (FQDN) given, try local computer name. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync /* Is a domain name missing? Then use the name of the local computer. */
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync hr = RTUTF16ToUnicode(&pKerberosLogon->LogonDomainName,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync false /* Just assign, no copy */);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::GetSerialization: Local computer name=%ls\n",
9a0f1c40d078ffc54c3209648d12c70f36480067vboxsync /* Fill in the username and password. */
98502a585f6eda30527b54f7df18dd3de3d3d7c6vboxsync false /* Just assign, no copy */);
9a0f1c40d078ffc54c3209648d12c70f36480067vboxsync false /* Just assign, no copy */);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Set credential type according to current usage scenario. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pKerberosLogon->MessageType = KerbWorkstationUnlockLogon;
ebe05ec36d1fcd24d62e7066dedcb4eb2e691358vboxsync pKerberosLogon->MessageType = KerbInteractiveLogon;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pKerberosLogon->MessageType = (KERB_LOGON_SUBMIT_TYPE)0; /* No message type required here. */
9a0f1c40d078ffc54c3209648d12c70f36480067vboxsync hr = StringCchLengthA(NEGOSSP_NAME_A, USHORT_MAX, &cchKerberosName);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync lsaszKerberosName.MaximumLength = lsaszKerberosName.Length + 1;
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync s = LsaLookupAuthenticationPackage(hLsa, &lsaszKerberosName,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pcpCredentialSerialization->ulAuthenticationPackage = ulAuthPackage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pcpCredentialSerialization->clsidCredentialProvider = CLSID_VBoxCredProvider;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* We're done -- let the logon UI know. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *pcpGetSerializationResponse = CPGSR_RETURN_CREDENTIAL_FINISHED;
f3701698f9d61fed78c320c3b35c64a0c63d6db1vboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::GetSerialization returned hr=0x%08x\n", hr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Called by LogonUI after a logon attempt was made -- here we could set an additional status
9a0f1c40d078ffc54c3209648d12c70f36480067vboxsync * text and/or icon.
9a0f1c40d078ffc54c3209648d12c70f36480067vboxsync * Currently not used.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @return HRESULT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param ntStatus NT status of logon attempt reported by Winlogon.
9a0f1c40d078ffc54c3209648d12c70f36480067vboxsync * @param ntSubStatus NT substatus of logon attempt reported by Winlogon.
9a0f1c40d078ffc54c3209648d12c70f36480067vboxsync * @param ppwszOptionalStatusText Pointer that receives the optional status text.
f3701698f9d61fed78c320c3b35c64a0c63d6db1vboxsync * @param pcpsiOptionalStatusIcon Pointer that receives the optional status icon.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVBoxCredProvCredential::ReportResult(NTSTATUS ntStatus,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync CREDENTIAL_PROVIDER_STATUS_ICON *pcpsiOptionalStatusIcon)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBoxCredProvVerbose(0, "VBoxCredProvCredential::ReportResult: ntStatus=%ld, ntSubStatus=%ld\n",