/**
 * 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;
}
Example #6
0
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;
}