Esempio n. 1
0
static DWORD FspNpGetCredentials(
    HWND hwndOwner, PWSTR Caption, DWORD PrevNpResult,
    DWORD CredentialsKind,
    PBOOL PSave,
    PWSTR UserName, ULONG UserNameSize/* in chars */,
    PWSTR Password, ULONG PasswordSize/* in chars */)
{
    DWORD NpResult;
    CREDUI_INFOW UiInfo;

    memset(&UiInfo, 0, sizeof UiInfo);
    UiInfo.cbSize = sizeof UiInfo;
    UiInfo.hwndParent = hwndOwner;
    UiInfo.pszCaptionText = Caption;
    UiInfo.pszMessageText = L"Enter credentials to unlock this file system.";

#if !defined(FSP_NP_CREDUI_PROMPT_NEW)
    NpResult = CredUIPromptForCredentialsW(&UiInfo, L"NONE", 0, 0,
        UserName, UserNameSize,
        Password, PasswordSize,
        PSave,
        CREDUI_FLAGS_GENERIC_CREDENTIALS |
        CREDUI_FLAGS_DO_NOT_PERSIST |
        CREDUI_FLAGS_ALWAYS_SHOW_UI |
        (0 != PrevNpResult ? CREDUI_FLAGS_INCORRECT_PASSWORD : 0) |
        (0 != PSave ? CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX : 0) |
        (FSP_NP_CREDENTIALS_PASSWORD == CredentialsKind ? 0/*CREDUI_FLAGS_KEEP_USERNAME*/ : 0));
#else
    WCHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1];
    ULONG AuthPackage = 0;
    PVOID InAuthBuf = 0, OutAuthBuf = 0;
    ULONG InAuthSize, OutAuthSize, DomainSize;

    InAuthSize = 0;
    if (!CredPackAuthenticationBufferW(
            CRED_PACK_GENERIC_CREDENTIALS, UserName, Password, 0, &InAuthSize) &&
        ERROR_INSUFFICIENT_BUFFER != GetLastError())
    {
        NpResult = GetLastError();
        goto exit;
    }

    InAuthBuf = MemAlloc(InAuthSize);
    if (0 == InAuthBuf)
    {
        NpResult = ERROR_NO_SYSTEM_RESOURCES;
        goto exit;
    }

    if (!CredPackAuthenticationBufferW(
        CRED_PACK_GENERIC_CREDENTIALS, UserName, Password, InAuthBuf, &InAuthSize))
    {
        NpResult = GetLastError();
        goto exit;
    }

    NpResult = CredUIPromptForWindowsCredentialsW(&UiInfo, PrevNpResult,
        &AuthPackage, InAuthBuf, InAuthSize, &OutAuthBuf, &OutAuthSize, PSave,
        CREDUIWIN_GENERIC | (0 != PSave ? CREDUIWIN_CHECKBOX : 0));
    if (ERROR_SUCCESS != NpResult)
        goto exit;

    DomainSize = sizeof Domain / sizeof Domain[0];
    if (!CredUnPackAuthenticationBufferW(0, OutAuthBuf, OutAuthSize,
        UserName, &UserNameSize, Domain, &DomainSize, Password, &PasswordSize))
    {
        NpResult = GetLastError();
        goto exit;
    }

    NpResult = ERROR_SUCCESS;

exit:
    if (0 != OutAuthBuf)
    {
        SecureZeroMemory(OutAuthBuf, OutAuthSize);
        CoTaskMemFree(OutAuthBuf);
    }

    if (0 != InAuthBuf)
    {
        SecureZeroMemory(InAuthBuf, InAuthSize);
        MemFree(InAuthBuf);
    }
#endif

    return NpResult;
}
// Collect the username and password into a serialized credential for the correct usage scenario 
// (logon/unlock is what's demonstrated in this sample).  LogonUI then passes these credentials 
// back to the system to log on.
HRESULT CCustomCredential::GetSerialization(
    CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE* pcpgsr,
    CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs, 
    PWSTR* ppwzOptionalStatusText, 
    CREDENTIAL_PROVIDER_STATUS_ICON* pcpsiOptionalStatusIcon
    )
{
    UNREFERENCED_PARAMETER(ppwzOptionalStatusText);
    UNREFERENCED_PARAMETER(pcpsiOptionalStatusIcon);

    HRESULT hr;

    WCHAR wsz[MAX_COMPUTERNAME_LENGTH+1];
    DWORD cch = ARRAYSIZE(wsz);

    DWORD cb = 0;
    BYTE* rgb = NULL;

    if (GetComputerNameW(wsz, &cch))
    {
        PWSTR pwzProtectedPassword;

		UserNameSerialized = FieldStrings[SFI_USERNAME];
		PasswordProtected = FieldStrings[SFI_PASSWORD];
        hr = ProtectIfNecessaryAndCopyPassword(PasswordProtected, _cpus, &pwzProtectedPassword);

        // Only CredUI scenarios should use CredPackAuthenticationBuffer.  Custom packing logic is necessary for
        // logon and unlock scenarios in order to specify the correct MessageType.
        if (CPUS_CREDUI == _cpus)
        {
            if (SUCCEEDED(hr))
            {
                PWSTR pwzDomainUsername = NULL;
                hr = DomainUsernameStringAlloc(wsz, UserNameSerialized.data(), &pwzDomainUsername);
                if (SUCCEEDED(hr))
                {
                    // We use KERB_INTERACTIVE_UNLOCK_LOGON in both unlock and logon scenarios.  It contains a
                    // KERB_INTERACTIVE_LOGON to hold the creds plus a LUID that is filled in for us by Winlogon
                    // as necessary.
                    if (!CredPackAuthenticationBufferW((CREDUIWIN_PACK_32_WOW & _dwFlags) ? CRED_PACK_WOW_BUFFER : 0, pwzDomainUsername, pwzProtectedPassword, rgb, &cb))
                    {
                        if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
                        {
                            rgb = (BYTE*)HeapAlloc(GetProcessHeap(), 0, cb);
                            if (rgb)
                            {
                                // If the CREDUIWIN_PACK_32_WOW flag is set we need to return 32 bit buffers to our caller we do this by 
                                // passing CRED_PACK_WOW_BUFFER to CredPacAuthenticationBufferW.
                                if (!CredPackAuthenticationBufferW((CREDUIWIN_PACK_32_WOW & _dwFlags) ? CRED_PACK_WOW_BUFFER : 0, pwzDomainUsername, pwzProtectedPassword, rgb, &cb))
                                {
                                    HeapFree(GetProcessHeap(), 0, rgb);
                                    hr = HRESULT_FROM_WIN32(GetLastError());
                                }
                                else
                                {
                                    hr = S_OK;
                                }
                            }
                            else
                            {
                                hr = E_OUTOFMEMORY;
                            }
                        }
                        else
                        {
                            hr = E_FAIL;
                        }
                        HeapFree(GetProcessHeap(), 0, pwzDomainUsername);
                    }
                    else
                    {
                        hr = E_FAIL;
                    }
                }
                CoTaskMemFree(pwzProtectedPassword);
            }
        }
        else
        {
            KERB_INTERACTIVE_UNLOCK_LOGON kiul;

            // Initialize kiul with weak references to our credential.
            hr = KerbInteractiveUnlockLogonInit(wsz, UserNameSerialized.data(), pwzProtectedPassword, _cpus, &kiul);

            if (SUCCEEDED(hr))
            {
                // We use KERB_INTERACTIVE_UNLOCK_LOGON in both unlock and logon scenarios.  It contains a
                // KERB_INTERACTIVE_LOGON to hold the creds plus a LUID that is filled in for us by Winlogon
                // as necessary.
                hr = KerbInteractiveUnlockLogonPack(kiul, &pcpcs->rgbSerialization, &pcpcs->cbSerialization);
            }
        }

        if (SUCCEEDED(hr))
        {
            ULONG ulAuthPackage;
            hr = RetrieveNegotiateAuthPackage(&ulAuthPackage);
            if (SUCCEEDED(hr))
            {
                pcpcs->ulAuthenticationPackage = ulAuthPackage;
                pcpcs->clsidCredentialProvider = CLSID_CCustomProvider;

                // In CredUI scenarios, we must pass back the buffer constructed with CredPackAuthenticationBuffer.
                if (CPUS_CREDUI == _cpus)
                {
                    pcpcs->rgbSerialization = rgb;
                    pcpcs->cbSerialization = cb;
                }

                // At this point the credential has created the serialized credential used for logon
                // By setting this to CPGSR_RETURN_CREDENTIAL_FINISHED we are letting logonUI know
                // that we have all the information we need and it should attempt to submit the 
                // serialized credential.
                *pcpgsr = CPGSR_RETURN_CREDENTIAL_FINISHED;
            }
            else 
            {
                HeapFree(GetProcessHeap(), 0, rgb);
            }
        }
    }
    else
    {
        DWORD dwErr = GetLastError();
        hr = HRESULT_FROM_WIN32(dwErr);
    }

	pLoginCommander->LoginFailed();
	return hr;
}