none
UserPrincipal.ChangePassword stops working after windows updates 3177108 and 3167679. RRS feed

  • Question

  • I have a web application that for years has been using the ChangePassword method on the UserPrincipal class to facilitate end user password resets. (The namespace is System.DirectoryServices.AccountManagement.)

    The web application is being hosted on a 2012R2 domain member server with 2 x 2012R2 DCs on the same LAN.

    This call has now stopped working and returns the exception "The system cannot contact a domain controller to service the authentication request. Please try again later. (Exception from HRESULT: 0x800704F1)  "

    If I remove windows updates 3177108 and 3167679 it starts working again. So I started digging deeper.

    The KB articles for this update partially explain the issue, but it doesn’t quite fit with my scenario; they say:

    “Currently, the ability to change the passwords of disabled or locked-out accounts is supported only by NTLM. It is not supported by the Kerberos protocol. This security update prevents the Negotiate process from falling back to NTLM for password change operations when Kerberos authentication fails. Therefore, you will no longer be able to change the password for disabled or locked-out accounts after you install this security update. It is not secure to change disabled or locked-out user account passwords by using NTLM. This is why the ability of Negotiate to fall back to NTLM is disabled by this security update.  “

    The problem with the above statement is that we are NOT trying to change disabled or locked out accounts, it is failing for all accounts.

    So my question is : Does the ChangePassword method use NTLM behind the scenes to do the change? If so, is there an alternative that will work in conjunction with the 2 above windows updates?

    It is a long shot posting this here but any wisdom is appreciated!

    Test code to reproduce the problem:

    using System.DirectoryServices.AccountManagement;
    
    string domainName = "xxxxxxxxx";
    string samAccountName = "xxxxxx.xxxx";
    string password = "xxxxxxxxxx!";
    string newPassword = "yyyyyyyyyy!";
    UserPrincipal up = null;
    PrincipalContext pn = null;
    //Get naming context
    pn = new PrincipalContext(ContextType.Domain, domainName, samAccountName, password);
    
    //find user
    up = UserPrincipal.FindByIdentity(pn, samAccountName);
    up.ChangePassword(password, newPassword);

    Thursday, August 18, 2016 12:27 PM

Answers

  • Hey again

    have done some testing, and it seems that you can do ChangePassword with DirectoryServices - as usual. The new Update have disabled the option for NTLM for ChangePassword, which means that Kerberos must be available for the context in order to make a ChangePassword. 

    Specify the NEGOTIATE flag on the principal context, as here: 

    var ctx = new PrincipalContext(ContextType.Domain, "domain", null, ContextOptions.Negotiate, "ctxUser", "xxxxxx");

    var user = UserPrincipal.FindByIdentity(ctx, "someUser");

    user.ChangePassword("old", "new");

    user.Save();

    EDIT: The default ContextOpetions is NEGOTIATE | SIGNING | SEALING. So it seems that this does not change the behavior. I did however experience that this change made it work, so going from NEGOTIATE+SIGNING+SEALING to ONLY NEGOTIATE made it work. But today, it does not change anything for me. So a little strange. 

    However, currently it works for me when specifying the full domain name for the context user we use in our serrvice.

    So, 

    var ctx = new PrincipalContext(ContextType.Domain, "domain", null, ContextOptions.Negotiate, "ctxUser@FULL.DOMAIN", "xxxxxx");

    var user = UserPrincipal.FindByIdentity(ctx, "someUser");

    user.ChangePassword("old", "new");

    user.Save();

    works, but without @FULL.DOMAIN, I get the error. 


    • Edited by Tue Skeltved Friday, August 19, 2016 9:21 AM
    • Marked as answer by timhowarduk Friday, August 19, 2016 9:43 AM
    Thursday, August 18, 2016 7:32 PM

All replies

  • We have the exact same issue - We have been using the ChangePassword calls on both UserPrincipal object and on DirectoryEntry.Invoke("ChangePassword", ..., ..) for years. 

    I would love to hear about alternatives as well. 

    And is it a permanent change or is it a bug that you cannot change password using these methods anymore - perhaps an incoming update to the DirectoryServices that fixes this?

    Any insight is appreciated :)

    EDIT: From https://support.microsoft.com/en-us/kb/3178465, "Note Even though you can no longer change the password for disabled or locked accounts, you can set the password by using Active Directory-based tools."

    So we should be able to do normal ChangePassword as usual using DirectoryServices i pressume?

    Thursday, August 18, 2016 6:03 PM
  • Hi

    Thanks for the response. It's good to know I'm not alone! I have also found this:

    http://en.community.dell.com/techcenter/iam/f/4991/t/19988817

    (see the answer)

    It seems that even DELL are having this problem with their Identity Management product.

    Thursday, August 18, 2016 6:25 PM
  • Hey again

    have done some testing, and it seems that you can do ChangePassword with DirectoryServices - as usual. The new Update have disabled the option for NTLM for ChangePassword, which means that Kerberos must be available for the context in order to make a ChangePassword. 

    Specify the NEGOTIATE flag on the principal context, as here: 

    var ctx = new PrincipalContext(ContextType.Domain, "domain", null, ContextOptions.Negotiate, "ctxUser", "xxxxxx");

    var user = UserPrincipal.FindByIdentity(ctx, "someUser");

    user.ChangePassword("old", "new");

    user.Save();

    EDIT: The default ContextOpetions is NEGOTIATE | SIGNING | SEALING. So it seems that this does not change the behavior. I did however experience that this change made it work, so going from NEGOTIATE+SIGNING+SEALING to ONLY NEGOTIATE made it work. But today, it does not change anything for me. So a little strange. 

    However, currently it works for me when specifying the full domain name for the context user we use in our serrvice.

    So, 

    var ctx = new PrincipalContext(ContextType.Domain, "domain", null, ContextOptions.Negotiate, "ctxUser@FULL.DOMAIN", "xxxxxx");

    var user = UserPrincipal.FindByIdentity(ctx, "someUser");

    user.ChangePassword("old", "new");

    user.Save();

    works, but without @FULL.DOMAIN, I get the error. 


    • Edited by Tue Skeltved Friday, August 19, 2016 9:21 AM
    • Marked as answer by timhowarduk Friday, August 19, 2016 9:43 AM
    Thursday, August 18, 2016 7:32 PM
  • I have this flag set in my code (negotiate) and received the error.  I found that my code still will not work and will throw the error (when it didn't before) in 3 cases:

    1)  I must now specify a domain for it to work.  If this was NULL before, it used to work.  (EDIT-- see below).

    2)  If I specify a valid service account when getting my principal context it will fail.  If this was given a valid service account before, it used to work.

    3)  The principalContext created with ContextType.Machine (working to change local passwords rather than Active Directory) will now fail with this error.

    EDIT:

    Something strange is going on.  Last week I had to specify a domain to get this to work.  (#1 above).  Now this week, I do not.  The behavior seems to change (others in this thread have noted this as well) so it's extremely confusing.

    If I specify a valid service account, it still fails with the "the system cannot contact a domain controller..." error.

    • Edited by Jigme2 Monday, August 22, 2016 7:22 PM
    Thursday, August 18, 2016 8:10 PM
  • Thank you - I will try this tomorrow.

    Tim

    Thursday, August 18, 2016 8:24 PM
  • Thank you for all of the contributions. I seem to have a working solution

    My working code is now:

    UserPrincipal up = null;
    PrincipalContext pn = null;
    pn = new PrincipalContext(ContextType.Domain, domainName, upn, password);
    
                //find user
    up =UserPrincipal.FindByIdentity(pn,IdentityType.UserPrincipalName, upn);
    up.ChangePassword(password, newPassword);
    up.Save();
    
    The key difference seems to be that when you setup the PrincipalContext, you NEED to use a user principal name, not a SAM account name. Note this might not be @domain in all cases, it depends on the UPN of the user.

    Friday, August 19, 2016 9:42 AM
  • The behavior of the returned Exceptions from the ChangePassword calls have also changed it seems. 

    Before, if a user tried to change a password using these calls while violating the domain set password policies, a specific exception for this error was thrown. 

    Now it seems, that whether you dont use UPN or any other error occurs, like the password policy error, you get the samme exception back: 

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

    Monday, August 22, 2016 8:34 AM
  • You wrote that it wont work without the @FULL.DOMAIN but what if i need to change the password for a local user?

    ctxUser@MachineName ?

    MachineName\ctxUser ?

    Tuesday, August 30, 2016 7:41 PM
  • Hi Tim, 

    thanks for this example. I've been struggling with this problem for a couple of weeks now.
    The strange thing: if I use this piece of code, the password of the user (a normal user without admin rights) is changed, but I still receive the folowing error after "up.ChangePassword()"

    When I try to logon again, the password has been changed but since I always get the same error (also when I use a wrong "old password"), there's no way for me to be sure the password really changed.

    Are you also facing this problem or do you have a workaround?

    Thanks a lot in advance!

    ERROR:

    An unhandled exception of type 'System.DirectoryServices.AccountManagement.PrincipalOperationException' occurred in System.DirectoryServices.AccountManagement.dll

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



    • Edited by UZITcommV Wednesday, August 31, 2016 8:22 AM
    Wednesday, August 31, 2016 8:21 AM
  • Did anyone found the code to change a local user (not domain user) since the two updates...

    Tried the negotiate option, user/password when creating the principal context option and it always fails.

    Some say that using a UPN instead of SamAccountName work but isnt UPN for AD only?

    Wednesday, August 31, 2016 5:27 PM
  • Here's my code... am i missing something? I keep getting the error...

    using (PrincipalContext ctx = new PrincipalContext(ContextType.Machine, Environment.MachineName, null, ContextOptions.Negotiate, username, oldPassword))
    using (UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, username))
    {
       user.ChangePassword(oldPassword, newPassword);
    }


    Thursday, September 1, 2016 3:32 PM
  • Did you check if the password changed anyway?
    At the moment, I also keep getting the same error but when I check, my passwords are changed anyway.

    At the moment, I just ignore the error but I'm never sure if everything went well...
    Anyone found a solution to this?

    Monday, September 5, 2016 1:49 PM
  • No i just tried it and the password remains the same. No changes happens, only getting the error message.
    Tuesday, September 6, 2016 12:21 PM
  • We are also getting the same error for both service account and normal user account password changes. We tried some work around or temporary solutions:

    For service accounts, if we add the web servers (where the changepass application is hosted) to logon restrictions, then the password change works successfully.

    For user accounts, if we reset the password (using prinicaluser.setpassword) first, then the password change works successfully.

    Not sure why those work arounds work though. Is there any other solutions or any permanent solution from Microsoft?

    Wednesday, September 7, 2016 4:28 PM
  • @dschowdary 

    For your second scenario, you must know that using the "SetPassword" method instead of "ChangePassword" requires administrator rights and bypass password policies, which may not be wanted.

    For the first scenario, could you explain what you mean with "add the web servers to logon restriction" please?

    Wednesday, September 7, 2016 5:11 PM
  • Hi

    All I can say is that the key thing to focus on is the context (1st line). For ages I was looking at the equivalent to your 2nd line.

    My guess would be to try ContextOptions.Sealing to tell it Kerberos or nothing.

    The bottom line seems to be that for reasons I don't know your first line would appear to be using NTLM rather than Kerberos to set the context, in spite of your efforts to tell it not to.

    Wednesday, September 7, 2016 8:43 PM
  • @TimHowardDuk

    Also tried it before and everytime i tried a ContextOptions different from Negotiate i receive an error message saying "The ContextOptions passed are invalid for the Machine store. Only ContextOptions.Negotiate is supported.


    Thursday, September 8, 2016 11:33 AM
  • Hi,

    are there any news regarding a  new hotfix? We got the same problem here.

    We uninstall KB3167679 and the change password was working again for local machine accounts. We are using the PrincipalContext to change the passwords in a c# web application on a Win 2008 R2 system.

    But after the next update cycle (this weekend) we got the same error again, but KB3167679 and KB3177108 are still not installed. Maybe the origin update were replaced by another patch.

    The following updates were installed this weekend:

    KB3185911, KB3184122, KB3179573, KB3177723, KB3177186, KB3175024, KB3172605

    What can we do to solve thie problem again, are there any recommendations once and for all?

    "The system detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you."

    I tried the different answers from Tim and Dominic in this thread, but got no final solution. The setPassword Method is not an option for me.

    Thanks for any help or news.

    Best Regards, Joe

    Monday, September 26, 2016 2:40 PM
  • Same thing here, chebbes1. KB3175024 is the culprit this time.
    Monday, September 26, 2016 6:34 PM
  • @Chebbes1

    I have not found any solution, still stuck with the problem.

    Tuesday, September 27, 2016 10:57 AM
  • Hello

    We have the same issue :(

    The context :

    * We have 3 AD Servers (W2K8R2)
    * Members servers W2K8, W2K8R2
    * An application wich use the method change.password... on W2K8* Servers to permit end-users ti change their password.

    The KB3167679 was uninstalled two weeks ago.

    The application worked fine a few days after, buth now it's KO :(

    AD servers were patched after removing and testing the application.

    Do i need to unsitall KB3167679  on AD servers ?

    Best Regards

    Fred



    Tuesday, September 27, 2016 4:49 PM
  • Thanks btimd, we had to uninstall KB3175024 and KB3172605 so that tha password change is working again for local machine users.

    We have had no problems with an AD environment in our application (change the password of AD users).

    @Dominic: We are going to set up a test system to isolate the problem in a non production environment. I will keep you updated as things progress.
    Wednesday, September 28, 2016 10:30 AM
  • Having the same issue as everyone else.  We are using a service account UPN to initialize the PrincipalContext and trying to change a user's password.  It is very intermittent whether or not it actually goes through with the password change.  Sometimes, even with an error, the password still gets changed.  
    Friday, September 30, 2016 1:03 AM
  • We have the same problem. We are using WinNT protocol, which has user format domain\username. basically it si IISADMPWD  IIS web app written in ASP. To solve the 0x800704F1 issue, we had to uninstall from IIS host server a dc servers following KB:

    KB3177108 
    KB3167679
    KB3175024 
    KB3172605

    This solved the issue for now.

    Regards 

    MK

    Friday, September 30, 2016 9:04 AM
  • For Service accounts, adding the changepass servers to "Logon restrictions" property of the AD account makes the password change work successfully.

    But we uninstalled the patch on all changepass servers and password changes are working fine. We are working with Microsoft for a permanent fix.

    Monday, October 3, 2016 9:39 PM
  • While you are working with Microsoft for the permanent fix, could you make sure it works too with a "change password for a local user" scenario too?? Not only for AD users.
    Tuesday, October 4, 2016 11:00 AM
  • 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).

    In other words, in the latest security rollups the "change password for a local user" scenario should be covered.

    Wednesday, October 12, 2016 5:26 AM
  • Still having issues after deploying the 10/11 patches..  I no longer get The system cannot contact a domain controller to service the authentication request. Please try again later. (Exception from HRESULT: 0x800704F1).

    I am using the domain name and the service account's SPN while changing the password.

    new PrincipalContext(ContextType.Domain,redacted.priv,serviceuser@redacted.priv,1234);

    New error is 

    System.Runtime.InteropServices.COMException: Exception from HRESULT: 0xC000000D

    Wednesday, October 12, 2016 9:53 PM
  • Thank you very much!!!

    After a week of searching and trying, this was the solution for my problem!

    Thursday, October 13, 2016 12:37 PM
  • Our servers (hosting our asp.net application and domain controllers) have KB3175024,  KB3172605 installed (not KB3177108, KB3167679) and I recently ran into this problem of not being able to change users passwords.

    I did a bit of testing and it seems that using the UPN instead of the sAMAccountName to create the PrincipalContext does work.

    Have you experienced any issues in other areas of your application(s) since making the switch from sAMAccountName to UPN?

    Friday, October 14, 2016 1:21 PM
  • Doing a bit more research and testing I found an issue when using the UPN instead of sAMAccountName to create the PrincipalContext. When calling  PrincipalContext.ValidateCredentials() and the user is not authenticated, the users badPwdCount is incremented by 2.

    Here is a forum post with the issue:  https://social.msdn.microsoft.com/Forums/vstudio/en-US/e2328cb6-8764-46bf-94eb-4773e2912d74/wrong-lockout-policy-count-when-using-principalcontextvalidatecredentials?forum=netfxbcl

    So unfortunately the work around in this post is to use sAMAccountName instead of UPN when creating the Principal context. Anyone have any ideas?

    Friday, October 14, 2016 1:44 PM
  • We have a custom built web application running in IIS that serves as our "web security" application.  Since the recent patches mentioned in this thread, it has broken the "changepassword" function of our application.  When "changePassword" is executed, we get the following error:

    "Unable to change password on User Account"
    Message: The system cannot contact a domain controller to service the authentication request. Please try again later. (Exception from HRESULT: 0x800704F1)
    Stack:    at System.DirectoryServices.AccountManagement.SDSUtils.ChangePassword(DirectoryEntry de, String oldPassword, String newPassword)
       at System.DirectoryServices.AccountManagement.ADStoreCtx.ChangePassword(AuthenticablePrincipal p, String oldPassword, String newPassword)
       at OscUtility.AD.AccountManagement.changePassword(String sUserName, String sOldPassword, String sNewPassword)

    Our developer says that it is failing because Kerberos is not being used (or even attempted) and that change password requires Kerberos.  I'm looking for solutions on the Active Directory side of things that might fix our application (and not require code changes).  Anyone had any success on that side of things?

    Friday, October 28, 2016 2:11 PM