VBoxCredProvProvider::VBoxCredProvProvider(void) : m_cRefs(1), m_pPoller(NULL), m_pCred(NULL), m_pEvents(NULL), m_fHandleRemoteSessions(false) { VBoxCredentialProviderAcquire(); VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Init); }
VBoxCredProvProvider::~VBoxCredProvProvider(void) { VBoxCredProvVerbose(0, "VBoxCredProv: Destroying\n"); if (m_pCred) { m_pCred->Release(); m_pCred = NULL; } if (m_pPoller) { m_pPoller->Shutdown(); delete m_pPoller; m_pPoller = NULL; } VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Terminated); VBoxCredentialProviderRelease(); }
/** * Checks and retrieves credentials provided by the host + does account lookup on eventually * renamed user accounts. * * @return IPRT status code. */ int VBoxCredProvCredential::RetrieveCredentials(void) { int rc = VbglR3CredentialsQueryAvailability(); if (RT_SUCCESS(rc)) { /* * Set status to "terminating" to let the host know this module now * tries to receive and use passed credentials so that credentials from * the host won't be sent twice. */ VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Terminating); rc = VbglR3CredentialsRetrieveUtf16(&m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], &m_apwszCredentials[VBOXCREDPROV_FIELDID_PASSWORD], &m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Retrieved credentials with rc=%Rrc\n", rc); } if (RT_SUCCESS(rc)) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: User=%ls, Password=%ls, Domain=%ls\n", m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], #ifdef DEBUG m_apwszCredentials[VBOXCREDPROV_FIELDID_PASSWORD], #else L"XXX" /* Don't show any passwords in release mode. */, #endif m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); /* * In case we got a "display name" (e.g. "John Doe") * instead of the real user name (e.g. "jdoe") we have * to translate the data first ... */ PWSTR pwszAcount; if (TranslateAccountName(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], &pwszAcount)) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Translated account name %ls -> %ls\n", m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], pwszAcount); if (m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) { RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) + sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]); } m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME] = pwszAcount; } else { /* * Okay, no display name, but maybe it's a * principal name from which we have to extract the domain from? * ([email protected] -> jdoe in domain my-domain.sub.net.com.) */ PWSTR pwszDomain; if (ExtractAccoutData(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], &pwszAcount, &pwszDomain)) { /* Update user name. */ if (m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) { RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) + sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]); } m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME] = pwszAcount; /* Update domain. */ if (m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]) { RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME], RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]) + sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); } m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME] = pwszDomain; VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Extracted account data pwszAccount=%ls, pwszDomain=%ls\n", m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); } } m_fHaveCreds = true; } else { /* If credentials already were retrieved by a former call, don't try to retrieve new ones * and just report back the already retrieved ones. */ if (m_fHaveCreds) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Credentials already retrieved\n"); rc = VINF_SUCCESS; } } VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Returned rc=%Rrc\n", rc); return rc; }
/** * Tells this provider the current usage scenario. * * @return HRESULT * @param enmUsageScenario Current usage scenario this provider will be * used in. * @param dwFlags Optional flags for the usage scenario. */ HRESULT VBoxCredProvProvider::SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO enmUsageScenario, DWORD dwFlags) { HRESULT hr = S_OK; DWORD dwErr; VBoxCredProvVerbose(0, "VBoxCredProv::SetUsageScenario: enmUsageScenario=%d, dwFlags=%ld\n", enmUsageScenario, dwFlags); m_enmUsageScenario = enmUsageScenario; switch (m_enmUsageScenario) { case CPUS_LOGON: case CPUS_UNLOCK_WORKSTATION: { VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Active); dwErr = LoadConfiguration(); if (dwErr != ERROR_SUCCESS) VBoxCredProvVerbose(0, "VBoxCredProv: Error while loading configuration, error=%ld\n", dwErr); /* Do not stop running on a misconfigured system. */ /* * If we're told to not handle the current session just bail out and let the * user know. */ if (!HandleCurrentSession()) break; if (!m_pPoller) { try { m_pPoller = new VBoxCredProvPoller(); AssertPtr(m_pPoller); int rc = m_pPoller->Initialize(this); if (RT_FAILURE(rc)) VBoxCredProvVerbose(0, "VBoxCredProv::SetUsageScenario: Error initializing poller thread, rc=%Rrc\n", rc); } catch (std::bad_alloc &ex) { NOREF(ex); hr = E_OUTOFMEMORY; } } if ( SUCCEEDED(hr) && !m_pCred) { try { m_pCred = new VBoxCredProvCredential(); AssertPtr(m_pPoller); hr = m_pCred->Initialize(m_enmUsageScenario); } catch (std::bad_alloc &ex) { NOREF(ex); hr = E_OUTOFMEMORY; } } else { /* All set up already! Nothing to do here right now. */ } /* If we failed, do some cleanup. */ if (FAILED(hr)) { if (m_pCred != NULL) { m_pCred->Release(); m_pCred = NULL; } } break; } case CPUS_CHANGE_PASSWORD: /* Asks us to provide a way to change the password. */ case CPUS_CREDUI: /* Displays an own UI. We don't need that. */ case CPUS_PLAP: /* See Pre-Logon-Access Provider. Not needed (yet). */ hr = E_NOTIMPL; break; default: hr = E_INVALIDARG; break; } VBoxCredProvVerbose(0, "VBoxCredProv::SetUsageScenario returned hr=0x%08x\n", hr); return hr; }
/** * Checks and retrieves credentials provided by the host + does account lookup on eventually * renamed user accounts. * * @return IPRT status code. */ int VBoxCredProvCredential::RetrieveCredentials(void) { PRTUTF16 pwszUser = NULL; PRTUTF16 pwszPassword = NULL; PRTUTF16 pwszDomain = NULL; int rc = VbglR3CredentialsQueryAvailability(); if (RT_SUCCESS(rc)) { /* * Set status to "terminating" to let the host know this module now * tries to receive and use passed credentials so that credentials from * the host won't be sent twice. */ VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Terminating); rc = VbglR3CredentialsRetrieveUtf16(&pwszUser, &pwszPassword, &pwszDomain); VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Retrieved credentials with rc=%Rrc\n", rc); } if (RT_SUCCESS(rc)) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Received credentials for user '%ls'\n", pwszUser); /* * In case we got a "display name" (e.g. "John Doe") * instead of the real user name (e.g. "jdoe") we have * to translate the data first ... */ PWSTR pwszExtractedName = NULL; if ( TranslateAccountName(pwszUser, &pwszExtractedName) && pwszExtractedName) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Translated account name '%ls' -> '%ls'\n", pwszUser, pwszExtractedName); RTMemWipeThoroughly(pwszUser, (RTUtf16Len(pwszUser) + 1) * sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(pwszUser); pwszUser = RTUtf16Dup(pwszExtractedName); CoTaskMemFree(pwszExtractedName); pwszExtractedName = NULL; } else { /* * Okay, no display name, but maybe it's a * principal name from which we have to extract the domain from? * ([email protected] -> jdoe in domain my-domain.sub.net.com.) */ PWSTR pwszExtractedDomain = NULL; if (ExtractAccoutData(pwszUser, &pwszExtractedName, &pwszExtractedDomain)) { /* Update user name. */ if (pwszExtractedName) { if (pwszUser) { RTMemWipeThoroughly(pwszUser, (RTUtf16Len(pwszUser) + 1) * sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(pwszUser); } pwszUser = RTUtf16Dup(pwszExtractedName); CoTaskMemFree(pwszExtractedName); pwszExtractedName = NULL; } /* Update domain. */ if (pwszExtractedDomain) { if (pwszDomain) { RTMemWipeThoroughly(pwszDomain, (RTUtf16Len(pwszDomain) + 1) * sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(pwszDomain); } pwszDomain = RTUtf16Dup(pwszExtractedDomain); CoTaskMemFree(pwszExtractedDomain); pwszExtractedDomain = NULL; } VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Extracted account name '%ls' + domain '%ls'\n", pwszUser ? pwszUser : L"<NULL>", pwszDomain ? pwszDomain : L"<NULL>"); } } m_fHaveCreds = true; } if (m_fHaveCreds) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Setting fields\n"); setField(VBOXCREDPROV_FIELDID_USERNAME, pwszUser, true /* fNotifyUI */); setField(VBOXCREDPROV_FIELDID_PASSWORD, pwszPassword, true /* fNotifyUI */); setField(VBOXCREDPROV_FIELDID_DOMAINNAME, pwszDomain, true /* fNotifyUI */); } VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Wiping ...\n"); VbglR3CredentialsDestroyUtf16(pwszUser, pwszPassword, pwszDomain, 3 /* cPasses */); VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Returned rc=%Rrc\n", rc); return rc; }