/** * Clears and frees the three strings. * * @param pszUser Receives pointer of the user name string to destroy. * Optional. * @param pszPassword Receives pointer of the password string to destroy. * Optional. * @param pszDomain Receives pointer of allocated domain name string. * Optional. * @param cPasses Number of wipe passes. The more the better + slower. */ VBGLR3DECL(void) VbglR3CredentialsDestroy(char *pszUser, char *pszPassword, char *pszDomain, uint32_t cPasses) { /* wipe first */ if (pszUser) RTMemWipeThoroughly(pszUser, strlen(pszUser) + 1, cPasses); if (pszPassword) RTMemWipeThoroughly(pszPassword, strlen(pszPassword) + 1, cPasses); if (pszDomain) RTMemWipeThoroughly(pszDomain, strlen(pszDomain) + 1, cPasses); /* then free. */ RTStrFree(pszUser); RTStrFree(pszPassword); RTStrFree(pszDomain); }
/** * Clears and frees the three strings. UTF-16 version. * * @param pwszUser Receives pointer of the user name string to destroy. * Optional. * @param pwszPassword Receives pointer of the password string to destroy. * Optional. * @param pwszDomain Receives pointer of allocated domain name string. * Optional. * @param cPasses Number of wipe passes. The more the better + slower. */ VBGLR3DECL(void) VbglR3CredentialsDestroyUtf16(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain, uint32_t cPasses) { /* wipe first */ if (pwszUser) RTMemWipeThoroughly(pwszUser, (RTUtf16Len(pwszUser) + 1) * sizeof(RTUTF16), cPasses); if (pwszPassword) RTMemWipeThoroughly(pwszPassword, (RTUtf16Len(pwszPassword) + 1) * sizeof(RTUTF16), cPasses); if (pwszDomain) RTMemWipeThoroughly(pwszDomain, (RTUtf16Len(pwszDomain) + 1) * sizeof(RTUTF16), cPasses); /* then free. */ RTUtf16Free(pwszUser); RTUtf16Free(pwszPassword); RTUtf16Free(pwszDomain); }
/** * Sets a credential provider field by first zero'ing out its current content in a (hopefully) secure manner, * then applying either the field's default or a new value. * * @return HRESULT * @param dwFieldID Field ID of the credential provider field to reset. * @param pcwszString String to set for the given field. Specify NULL for setting the provider's default value. * @param fNotifyUI Whether to notify the LogonUI about the reset. */ HRESULT VBoxCredProvCredential::setField(DWORD dwFieldID, const PRTUTF16 pcwszString, bool fNotifyUI) { if (dwFieldID >= VBOXCREDPROV_NUM_FIELDS) return E_INVALIDARG; HRESULT hr = S_OK; PRTUTF16 pwszField = m_apwszFields[dwFieldID]; if (pwszField) { /* First, wipe the existing value thoroughly. */ RTMemWipeThoroughly(pwszField, (RTUtf16Len(pwszField) + 1) * sizeof(RTUTF16), 3 /* Passes */); /* Second, free the string. */ RTUtf16Free(pwszField); } /* Either fill in the default value or the one specified in pcwszString. */ pwszField = RTUtf16Dup(pcwszString ? pcwszString : s_VBoxCredProvDefaultFields[dwFieldID].desc.pszLabel); if (pwszField) { m_apwszFields[dwFieldID] = pwszField; /* Update the pointer. */ if ( m_pEvents && fNotifyUI) /* Let the logon UI know if wanted. */ { hr = m_pEvents->SetFieldString(this, dwFieldID, pwszField); } } else hr = E_OUTOFMEMORY; VBoxCredProvVerbose(0, "VBoxCredProvCredential::setField: Setting field dwFieldID=%ld to '%ls', fNotifyUI=%RTbool, hr=0x%08x\n", dwFieldID, #ifdef DEBUG pwszField, #else /* Don't show any passwords in release mode. */ dwFieldID == VBOXCREDPROV_FIELDID_PASSWORD ? L"XXX" : pwszField, #endif fNotifyUI, hr); return hr; }
/** * Frees a formerly allocated PUNICODE_STRING. * * @param pUnicode String to free. */ void VBoxCredProvCredential::UnicodeStringFree(PUNICODE_STRING pUnicode) { if (!pUnicode) return; if (pUnicode->Buffer) { Assert(pUnicode->MaximumLength); /* Make sure to wipe contents before free'ing. */ RTMemWipeThoroughly(pUnicode->Buffer, pUnicode->MaximumLength /* MaximumLength is bytes! */, 3 /* Passes */); CoTaskMemFree(pUnicode->Buffer); pUnicode->Buffer = NULL; } pUnicode->Length = 0; pUnicode->MaximumLength = 0; }
RTDECL(uint32_t) RTCrPkixSignatureRelease(RTCRPKIXSIGNATURE hSignature) { PRTCRPKIXSIGNATUREINT pThis = hSignature; if (pThis == NIL_RTCRPKIXSIGNATURE) return 0; AssertPtrReturn(pThis, UINT32_MAX); AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, UINT32_MAX); uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs); Assert(cRefs < 64); if (!cRefs) { pThis->u32Magic = ~RTCRPKIXSIGNATUREINT_MAGIC; if (pThis->pDesc->pfnDelete) pThis->pDesc->pfnDelete(pThis->pDesc, pThis->abState, pThis->fSigning); size_t cbToWipe = RT_OFFSETOF(RTCRPKIXSIGNATUREINT, abState[pThis->pDesc->cbState]); RTMemWipeThoroughly(pThis, cbToWipe, 6); RTMemFree(pThis); } return cRefs; }
static void doMemWipeThoroughly(RTTEST hTest) { for (uint32_t p = 0; p < RTRandU32Ex(1, 64); p++) { size_t cbAlloc = RTRandS32Ex(1, _1M) * sizeof(uint8_t); RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Testing wipe #%.02RU32 (%u bytes) ...\n", p + 1, cbAlloc); void *pvBuf = RTMemAlloc(cbAlloc); if (!pvBuf) { RTTestIFailed("No memory for first buffer (%z bytes)\n", cbAlloc); continue; } RTRandBytes(pvBuf, cbAlloc); void *pvWipe = RTMemDup(pvBuf, cbAlloc); if (!pvWipe) { RTMemFree(pvBuf); RTTestIFailed("No memory for second buffer (%z bytes)\n", cbAlloc); continue; } size_t cbWipeRand = RTRandU32Ex(1, cbAlloc); RTMemWipeThoroughly(pvWipe, RT_MIN(cbAlloc, cbWipeRand), p /* Passes */); if (!memcmp(pvWipe, pvBuf, cbAlloc)) RTTestIFailed("Memory blocks must differ (%z bytes, 0x%p vs. 0x%p)!\n", cbAlloc, pvWipe, pvBuf); RTMemFree(pvWipe); RTMemFree(pvBuf); } }
/** * 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; }
/** * 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; }