c# Change AD password Directoryservices

4

Im trying to get the following code to work, problem is, sometimes it does, sometimes it doesnt. when it fails it gives the error 0x800704F1 "the system cannot contact a domain controller to service the authentication request" I'd say about 90% of the time it fails. I have tried giving it a static DC by adding it behind the contexttype this sadly did not help. On an admin user it works always.. however i do believe users are supposed to be able to change their own password. The error is triggered on the user.changepassword line

I hope someone else has a bright idea.

        using (var context = new PrincipalContext(ContextType.Domain))
        {
            using (var user = UserPrincipal.Current)
            {
                try
                {
                    user.ChangePassword(txt_old.Text, txt_new.Text);
                    user.Save();

                }
                catch(Exception p)
                {
                    if (p.HResult.Equals("0x800708C5"))//Not secure enough according to password policy
                    {
                        MessageBox.Show("Volgens het systeem is uw nieuwe wachtwoord niet veilig genoeg, voldoet het aan alle eisen?", "Niet gelukt", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }
                    else if (p.HResult.Equals("0x80070056")) //Wrong current password
                    {
                        MessageBox.Show("U heeft een verkeerd huidig wachtwoord ingevult, probeer het nogmaals", "Verkeerd wachtwoord", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }
                    else if (p.InnerException.ToString().Contains("0x80070775")) //Temporarly locked out.
                    {
                        MessageBox.Show("Uw account is tijdelijk vergrendeld door te veel pogingen tot in te loggen met een foutief wachtwoord. Probeer het over 15minuten nogmaals of neem contact op met de helpdesk.", "vergrendeld.", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }
                    else
                    {
                        MessageBox.Show(System.Security.Principal.WindowsIdentity.GetCurrent().Name + Environment.NewLine + p.HResult + Environment.NewLine + p.Message);
                        return;
                    }
                }
            }
        }
c#
active-directory
asked on Stack Overflow Aug 16, 2016 by Kage

4 Answers

9

The two Windows updates 3177108 and 3167679 have changed the behavior of ChangePassword.

There is a thread here about the issue: https://social.msdn.microsoft.com/Forums/vstudio/en-US/77dc733e-a13d-4349-9088-8065b85d5c3f/userprincipalchangepassword-stops-working-after-windows-updates-3177108-and-3167679?forum=netfxbcl

It seems, that you now have to specify a valid UPN when creating the PrincipalContext.

Before you could use a IP as endpoint when creating the context, now it seems it has to be a correct domain name aswell.

Furthermore, you now always receive the same exception when an error occurs - we used to receive the password policy exception for users choosing insufficient passwords, now we get:

System.DirectoryServices.AccountManagement.PrincipalOperationException: The system cannot contact a domain controller to service the authentication request. Please try again later. (Exception from HRESULT: 0x800704F1)

UPDATE 04-10-2016: The exception displayed above is really the general/generic error received for just about anything when calling ChangePassword after the updates. If for instance some of the ports involved in the protocol is blocked by a firewall, you get this one as well (applicable if you call from a server/machine that is not domain joined).

Good resource for required ports: https://technet.microsoft.com/en-us/library/dd772723(v=ws.10).aspx Note that the dynamic range is required as well.

If the user is not allowed to change password (domain policy, circumvent by setting MUST CHANGE AT NEXT LOGON FLAG) you also receive this exception.

answered on Stack Overflow Aug 22, 2016 by Tue Skeltved • edited Oct 4, 2016 by Tue Skeltved
2

Your problem may be that a password policy violation has occurred. That is, for example, if you have a password policy in place where users can't change their passwords to be one of their last 5, as an example, if they try to change to one of their last 5 you'll see this error thrown in my experience.

The error just before the exception you report (in my case) looks like this: TargetInvocationException: COM error attempting to change an Active Directory password..

So i'd check your password policies and make sure that your users in these cases aren't violating it.

answered on Stack Overflow Aug 16, 2016 by robertpb
2

UPDATE: 10/12/2016: Microsoft has updated this article: https://support.microsoft.com/en-us/kb/3177108 . Here they have given us problems created by the original "fixes" as well as some tips for working with Kerberos and self-service password reset.

As of October 11, 2016 Microsoft re-released the patches associated with https://technet.microsoft.com/en-us/library/security/ms16-101.aspx to resolve issues caused by the original updates (which you can read in https://support.microsoft.com/en-us/kb/3177108 including the fact that you could no longer change passwords on local accounts).


I believe I have the answer. Microsoft recently patched Windows so that NTLM can't be used to change passwords anymore.

Solution #1 (the "hammer"): Try removing either one or both of these KB updates on your server running the code.

https://support.microsoft.com/en-us/kb/3177108

https://support.microsoft.com/en-us/kb/3167679

When you say you can change the password as an admin, do you mean only when your forms application is running on an admin's machine? Is the challenge when the application is running on a non-admin's machine?

I was able to take your code and get it work as is as well as changing the following:

using (var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "test.user0001"))

and

using (var user = UserPrincipal.FindByIdentity(context, IdentityType.UserPrincipalName, "test.user0001@webactivedirectory.com"))

Using either one of these lines as well as yours (getting the current user) I was able to change admin and non-admin passwords alike. My question is whether your error happens when you have the forms app running on a non-admins machine.

answered on Stack Overflow Aug 18, 2016 by robertpb • edited Oct 12, 2016 by robertpb
1

I witnessed this from the sysadmin side on two different occasions: two applications with password management features had to be installed on two freshly deployed servers, which had of course been fully patched; in both cases, changing passwords failed with an error about the application being unable to contact a domain controller (which, of course, was actually there and available).

One application was a closed-source vendor-supplied one (CyberArk's Privileged Session Manager), while the other one was an in-house application developed by the customer where I'm currently working; in the second case, I was able to take a look at the code, which was indeed similar to that used in the original question.

Sadly, actually fixing the code was not an option in both cases: for the first application we had to report a bug to the application vendor, while for the second one we had to report a bug to the internal development team working on the application, be we couldn't get an immediate fix in either case. Management wanted both applications working now, thus we had to remove the offending updates (I know, this is bad and not a solution but a lazy and dangerous workaround, and I tried all I could to avoid that; but management is management, so... meh).

Anyway, the reason I'm jumping in with this answer: apart from removing KB3177108 and KB3167679, in my case (both cases) we also had to remove KB3175024 and KB3174644; while those two updates were installed, the password change function still refused to work, even after removing the first two ones.

So, if you find yourself in a situation where you can't fix the code, and removing KB3177108 and KB3167679 doesn't solve the issue, then you can try removing also KB3175024 and KB3174644.

answered on Stack Overflow Sep 30, 2016 by Massimo • edited Sep 30, 2016 by Massimo

User contributions licensed under CC BY-SA 3.0