windows-Credential-Provider-library icon indicating copy to clipboard operation
windows-Credential-Provider-library copied to clipboard

How can I handle password expiry in the credential provider?

Open Mohitkiran opened this issue 5 years ago • 20 comments

Hi thanks for this project it helped me alot, can you please help me out how can I handle password expiry in credential provider where the user should be prompted to change password and should be able to change password from my credential provider when his password expired, Thank you.

Mohitkiran avatar Nov 24 '19 11:11 Mohitkiran

https://docs.microsoft.com/en-gb/windows/win32/api/credentialprovider/ne-credentialprovider-credential_provider_usage_scenario

CPUS_CHANGE_PASSWORD should be good enough.

DavidWeiss2 avatar Dec 17 '19 21:12 DavidWeiss2

Thanks for the reply, what changes need to be done in getSerialization while implementing this CPUS_CHANGE_PASSWORD scenario? What method should I call to pass the old password and new password?

Mohitkiran avatar Dec 20 '19 11:12 Mohitkiran

Hello, KerbChangePasswordPack (https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/929b7283-562c-464f-ad4a-ba6699b52dbf/about-credential-providermodify-the-password-successlybut-the-password-is-null-when-the-password?forum=windowssdk) Regards,

multiOTP avatar Dec 20 '19 12:12 multiOTP

The remarks on this: https://docs.microsoft.com/en-us/windows/win32/api/credentialprovider/nf-credentialprovider-icredentialprovidercredential-getserialization

I am using the link to the source for maintainability. if it will be changed in the docs the answer will remain the same.

DavidWeiss2 avatar Dec 20 '19 18:12 DavidWeiss2

Hello, KerbChangePasswordPack (https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/929b7283-562c-464f-ad4a-ba6699b52dbf/about-credential-providermodify-the-password-successlybut-the-password-is-null-when-the-password?forum=windowssdk) Regards,

Nice to see you guys here 😃

DavidWeiss2 avatar Dec 20 '19 18:12 DavidWeiss2

Thanks guys those links should help! Also guys how can I make this credential provider compatible for windows 8 and window 2012 R2 server? What steps are needed to be performed to achieve this? I tried to install in windows 2012 R2 server and I can't see the my credential provider in login screen, I checked the registry values and CLSID of my credential provider is added under HKLM/SOFTWARE/Microsoft/Windows/Current Version/Authentication/Credential Providers and also .Dll is placed in system 32.

Mohitkiran avatar Dec 20 '19 19:12 Mohitkiran

Can you give me more info?

DavidWeiss2 avatar Dec 21 '19 18:12 DavidWeiss2

Do you have VCRedist Visual Studio C++ runtimes installed ?

multiOTP avatar Dec 22 '19 09:12 multiOTP

Do you have VCRedist Visual Studio C++ runtimes installed ?

Yes I have installed VCRedist 2015 x64 in the Windows R2 2012 server, still I am not able to see my custom CP in sign in options.

Mohitkiran avatar Dec 23 '19 08:12 Mohitkiran

Can you give me more info?

Hi David, can you tell what info you need so that I can mention that specifically?

Mohitkiran avatar Dec 23 '19 08:12 Mohitkiran

Do you have VCRedist Visual Studio C++ runtimes installed ?

Yes I have installed VCRedist 2015 x64 in the Windows R2 2012 server, still I am not able to see my custom CP in sign in options.

Same issue! How did you solved that?

professormahi avatar May 13 '20 11:05 professormahi

hi, first of all thanks to DavidWeiss2 bcz of his github details about cp that helped me a lot. i am new to credential provider and i am trying to do a change cache credential password (password change).
In CSampleCredential.cpp file in GetSerialization(...) function

case CPUS_CHANGE_PASSWORD: if(newPassword.Compare(confirmPassword) == 0) { KERB_CHANGEPASSWORD_REQUEST kcpr; ZeroMemory(&kcpr, sizeof(kcpr));

                    hr = UnicodeStringInitWithString(m_domain, &kcpr.DomainName);

                    if (SUCCEEDED(hr))
                    {
                        hr = UnicodeStringInitWithString(m_username, &kcpr.AccountName);

                        if (SUCCEEDED(hr))
                        {
                            hr = UnicodeStringInitWithString(_rgFieldStrings[SFI_PASSWORD], &kcpr.OldPassword);
                            hr = UnicodeStringInitWithString(_rgFieldStrings[SFI_NEWPASSWORD], &kcpr.NewPassword);

                            if (SUCCEEDED(hr))
                            {
                                kcpr.MessageType = KerbChangePasswordMessage;
                                kcpr.Impersonating = FALSE;
                                hr = KerbChangePasswordPack( kcpr, &pcpcs->rgbSerialization, &pcpcs->cbSerialization);

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

                                        *pcpgsr = CPGSR_RETURN_CREDENTIAL_FINISHED;
                                    }
                                }
                            }
                        }
                    }
                }
        break;

and In "helpers.cpp" file you have to enter a new function code if this function is not there for password change //pack the struct of KERB_CHANGEPASSWORD_REQUEST HRESULT KerbChangePasswordPack( const KERB_CHANGEPASSWORD_REQUEST& kcpr, BYTE** prgb, DWORD* pcb ) { HRESULT hr;

DWORD cb = sizeof(kcpr) +
    kcpr.DomainName.Length +
    kcpr.AccountName.Length +
    kcpr.OldPassword.Length +
    kcpr.NewPassword.Length;

KERB_CHANGEPASSWORD_REQUEST* pkcpr = (KERB_CHANGEPASSWORD_REQUEST*)CoTaskMemAlloc(cb);

if (pkcpr)
{
    pkcpr->MessageType = kcpr.MessageType;

    BYTE* pbBuffer = (BYTE*)pkcpr + sizeof(KERB_CHANGEPASSWORD_REQUEST);

    _UnicodeStringPackedUnicodeStringCopy(kcpr.DomainName, (PWSTR)pbBuffer, &pkcpr->DomainName);
    pkcpr->DomainName.Buffer = (PWSTR)(pbBuffer - (BYTE*)pkcpr);
    pbBuffer += pkcpr->DomainName.Length;

    _UnicodeStringPackedUnicodeStringCopy(kcpr.AccountName, (PWSTR)pbBuffer, &pkcpr->AccountName);
    pkcpr->AccountName.Buffer = (PWSTR)(pbBuffer - (BYTE*)pkcpr);
    pbBuffer += pkcpr->AccountName.Length;

    _UnicodeStringPackedUnicodeStringCopy(kcpr.OldPassword, (PWSTR)pbBuffer, &pkcpr->OldPassword);
    pkcpr->OldPassword.Buffer = (PWSTR)(pbBuffer - (BYTE*)pkcpr);
    pbBuffer += pkcpr->OldPassword.Length;

    _UnicodeStringPackedUnicodeStringCopy(kcpr.NewPassword, (PWSTR)pbBuffer, &pkcpr->NewPassword);
    pkcpr->NewPassword.Buffer = (PWSTR)(pbBuffer - (BYTE*)pkcpr);

    *prgb = (BYTE*)pkcpr;
    *pcb = cb;

    hr = S_OK;
}
else
{
    hr = E_OUTOFMEMORY;
}

return hr;

}

now the problem for me is, what are the changing i want to do except from these. like how to change usage scenario to cpus_change_password and how to pass control to get serialization so that to run these code.

like what are the other things i need to do except from these

gokulraj381 avatar Jul 02 '20 20:07 gokulraj381

I think you can replicate the password change scenario by changing password expiry policies in active directory for the test user. @gokulraj381

Mohitkiran avatar Jul 03 '20 05:07 Mohitkiran

NO , my problem is when the user is offline (like he is not near domain controller). i want to change his password (as he is not under domain controller) in cache credential of his laptop. to do that is there any API or i need to implement CPUS_CHANGE_PASSWORD

gokulraj381 avatar Jul 03 '20 08:07 gokulraj381

can i get ur instagram id or gmail id so that i can contact you and ask about my doubt

gokulraj381 avatar Jul 03 '20 08:07 gokulraj381

When you are not able to reach domain controller and you want to change the cached password of domain user that use case is not supported up to my knowledge, [email protected].

Mohitkiran avatar Jul 03 '20 09:07 Mohitkiran

but brother the domain password are stored in our laptop as cache credential (to authenticate when the dc is not available). now i just need to change that cache credential password. do u know anybody who knows about co better??

gokulraj381 avatar Jul 03 '20 11:07 gokulraj381

Like I said you can't change the password when your domain is offline even though the password is cached locally. Please follow this article https://social.technet.microsoft.com/Forums/windows/en-US/b723142a-33f5-4b02-95b1-5a5daac606b1/how-to-reset-password-of-user-while-not-connected-to-domain-using-local-admin-account?forum=w7itprosecurity#:~:text=Short%20answer%20is%20that%20you,controller%2C%20not%20the%20local%20machine.

Mohitkiran avatar Jul 03 '20 14:07 Mohitkiran

brother that is what i am saying ,the cached copy which he told , that is the thing I want to change !!! for that he told that we need old password and i also have it. the method how to do it is the question

for referal his answer

Locally you just has a cached copy of it, but that's not the master copy of it (which is why you don't see the user listed as a local user on the machine).

In order for them to reset their password they'll need to enter their existing password in any case, so even if you could initiate it locally it wouldn't help without the existing password.

the existing password i have it, i just want the method

gokulraj381 avatar Jul 03 '20 17:07 gokulraj381

Hello, I am a developer from China. I would like to ask a question about how to make remote login users have the same credentials as those who log in locally.

Vincent2019 avatar Jul 28 '21 09:07 Vincent2019