Credential Providers V2 - 提交后添加代码并检查用户密码

Credential Providers V2 - Add code after submit and check user's password

单击提交按钮并检查用户密码后如何添加我的代码?

我在成功调用 KerbInteractiveUnlockLogonPack 和 RetrieveNegotiateAuthPackage 后将我的代码添加到 GetSerialization 函数中。但是在这种状态下先运行我的代码,然后检查用户密码。

我想先检查用户密码,如果密码正确,那么 运行 我的代码。我该怎么办?

if (_fIsLocalUser)
{
    PWSTR pwzProtectedPassword;
    hr = ProtectIfNecessaryAndCopyPassword(_rgFieldStrings[SFI_PASSWORD], _cpus, &pwzProtectedPassword);
    if (SUCCEEDED(hr))
    {
        PWSTR pszDomain;
        PWSTR pszUsername;
        hr = SplitDomainAndUsername(_pszQualifiedUserName, &pszDomain, &pszUsername);
        if (SUCCEEDED(hr))
        {
            KERB_INTERACTIVE_UNLOCK_LOGON kiul;
            hr = KerbInteractiveUnlockLogonInit(pszDomain, pszUsername, 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_CSample;
                        // 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;
                    }
                }
            }
            CoTaskMemFree(pszDomain);
            CoTaskMemFree(pszUsername);
        }
        CoTaskMemFree(pwzProtectedPassword);
    }
}

我在我的代码中找到以下行来检查 username/password 对:

    bRet = LogonUserExA(lpszUsername, NULL, lpszPassword, LOGON32_LOGON_NETWORK, 
        LOGON32_PROVIDER_DEFAULT, NULL, NULL, NULL, NULL, NULL);

lpszUsername 我们以 domain\useruser@domain.
形式之一提供完整的 UPN 关键常量是 LOGON32_LOGON_NETWORK:

This logon type is intended for high performance servers to authenticate plaintext passwords. The LogonUserEx function does not cache credentials for this logon type.

有关参数和常量值的详细信息,请参阅 MS Docs 并查看备注部分。

在您的情况下,它可能如下所示:

if(LogonUserEx(_pszQualifiedUserName, NULL, _rgFieldStrings[SFI_PASSWORD],
    LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, NULL, NULL, NULL, NULL, NULL))
{
    ...
}