Solved

Change Active Directory User Password method SetPassword and ASP.Net

Posted on 2004-09-20
18
1,823 Views
Last Modified: 2007-12-19
Hi,

I cannot make the following code work in asp.net. It works fine in Console application.

string strLDAP = "LDAP://192.168.0.2CN=jdoe,OU=sample_ou,DC=MYDOMAIN,DC=local";
               DirectoryEntry entry  = new DirectoryEntry(strLDAP,"administrator","abcde",AuthenticationTypes.ServerBind);
               object native = entry.NativeGuid;
               entry.Invoke("SetPassword",new object[] {"testing"});
               Response.Write("Authenticated.<br>");
               Response.Write(entry.Properties["name"].Value);

This always give me the exception: System.Runtime.InteropServices.COMException: One or more input parameters are invalid
at entry.Invoke("SetPassword",new object[] {"testing"});

I have already tried using the AuthenticationType as a secure socket layer but that gave me "The server is not operational." . This thing is really annoying and wants me to shift my application to Windows as it works fine there. Any suggestions regarding changing the user password in active directory using ASP.net will be very helpful.

Thanks, Nauman.
0
Comment
Question by:nauman_ahmed
18 Comments
 
LVL 25

Author Comment

by:nauman_ahmed
ID: 12104507
I have already searched a lot on the net and tried almost everything. I will be really very thankful if a working solution is posted.

Thanks, Nauman.
0
 
LVL 16

Expert Comment

by:RobertRFreeman
ID: 12106108
Can you access Active Directory at all from the web server?
0
 
LVL 20

Accepted Solution

by:
ihenry earned 500 total points
ID: 12110526
Hi nauman,
I use the following function to reset user password. The userName parameters need to be a "Domain Admins" or "Account operators (Domain Account operators)" or any user which has proper rights to change password.

private String adminAccountName = @"Domain\Admins";
private String adminPassword = @"adminpwd";
public void ChangePassword(String ldapPath, String userName, String newPassword)
{
      DirectoryEntry de = new DirectoryEntry(ldapPath, adminAccountName, adminPassword, AuthenticationTypes.Secure);
      DirectorySearcher ds = new DirectorySearcher(de);

      String qry = String.Format("(&(objectCategory=person)(sAMAccountName={0}))", userName);
      ds.Filter = qry;
      ds.Sort.PropertyName = "cn";
      try
      {
            SearchResult sr = ds.FindOne();
            DirectoryEntry user = sr.GetDirectoryEntry();
            user.Invoke("SetPassword", new object[] {"" + newPassword + ""} );
            user.CommitChanges();
      }
      catch (Exception)
      {
            throw;
      }
      finally
      {
            if (de != null) de.Dispose();
            if (ds != null) ds.Dispose();
      }
}
0
 
LVL 25

Author Comment

by:nauman_ahmed
ID: 12112031
Thanks for the replies. I have noticed one thing in the LDAP connection string that if I use the WinNt: prefix, SetPassword  work fine however if I use the connection string having the LDAP: prefix it gives me an exception where I invoke the SetPassword command.

JHenry: How you are defining the connection string for active directory? Can you post it here? Also currently I am trying to manange the active directory from another server. Will this make any difference?
 
Thanks, Nauman.
0
 
LVL 20

Expert Comment

by:ihenry
ID: 12112369
The your ldap path looks incorrect (if it's not typo error), it should be
string strLDAP = "LDAP://192.168.0.2/CN=jdoe,OU=sample_ou,DC=MYDOMAIN,DC=local";

This is the connection string format for ldap provider
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adsi/adsi/ldap_adspath.asp

I found WinNT provider is giving weird behaviour for some reasons especially when the code is running in ASP.NET environment. You should use ldap provider when accessing active directory.

Have you tried my code?
0
 
LVL 20

Expert Comment

by:ihenry
ID: 12114660
Nauman, to get SetPassword to work your codes need to do the following
1. bind to a user account which has proper access right ("Reset Password" extended control access right) to set the password.
2. use secure binding (SSL or kerberos) instead of simple binding.
3. make sure the supply new password match DC password policy complexity.
0
 
LVL 25

Author Comment

by:nauman_ahmed
ID: 12115545
Jhenry,

I am trying to use the method that you have used to reset the password but I am getting System.UnauthorizedAccessException: Access is denied. Impersonation is true for my application and I am logging in using the admin account. Any suggestions?

Thanks, Nauman.
0
 
LVL 20

Expert Comment

by:ihenry
ID: 12120572
Can you give me more information of the parameters being passed to the function, the provider type, the binding user account type, and asp.net authentication type. Do you have password policy enabled in the DC and do you have SSL setup or kerberos enabled in the active directory?
0
 
LVL 20

Expert Comment

by:ihenry
ID: 12125342

Nauman,

When invoking SetPassword, LDAP provider initially tries to establish 128-bit SSL connection. If the connection is unsuccessful, second attempt is to try to use Kerberos. And if Kerberos is unsuccessful, it then calls the AD specific network management API, NetUserChangePassword function.

Since with SetPassword you can change a user password without need to know the original password, the caller must have Reset Password extended control access right which usually given out to Domain Admins or Account Operators (Domain Account Operators). If you want something for your app users to change their own password, using SetPassword is not a good way to go. Because you need to grant such level of permission to all users and use ChangePassword would be a better choice.

IADsUser::SetPassword
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adsi/adsi/iadsuser_setpassword.asp

NetUserChangePassword
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netuserchangepassword.asp

User-Change-Password extended right
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adschema/adschema/r_user_change_password.asp

IADsUser::ChangePassword
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adsi/adsi/iadsuser_changepassword.asp
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 20

Expert Comment

by:ihenry
ID: 12125645
>> System.UnauthorizedAccessException: Access is denied.
>> Impersonation is true for my application...
>> I am logging in using the admin account..

Another reason might be caused... if you use my method and adminAccountName var not equal to Admin account then rely on asp.net context user (impersonate to true, logging with admin account, "Integrated Authentication" is selected in IIS and AD relies on different machine), SetPassword won't work. This is due to the double-hop issue. The good practice is always passing hard credentials to your DirectoryServices code through the class constructor, or by using the username and password properties with a user account that has sufficient access rights to do a particular task.
0
 
LVL 25

Author Comment

by:nauman_ahmed
ID: 12126162
Thanks JHenry and your help is really great :) Can you tell me if Kerberos authetication is enabled by default on Windows 2003 Server and if SSL communication can work by just installing the SSL certificate on the server or there are some additional steps involve in this kind of communication.

Thanks, Nauman.
0
 
LVL 25

Author Comment

by:nauman_ahmed
ID: 12126181
Also is it possible to delete user from the ActiveDirectory? If so which method should be used?

Thanks, Nauman.
0
 
LVL 20

Expert Comment

by:ihenry
ID: 12126867

Try to setup a network sniffer to sniff of the traffic to know what protocol is being used. Normally, SSL/LDAP is port 636 and the Kerberos set password port is 464 (If I'm not mistaken). SSL here means, an SSL connection must be established from client to Server. Here some articles from microsoft regarding this matter.

http://www.microsoft.com/technet/prodtechnol/windowsserver2003/technologies/security/tkerbdel.mspx
http://www.microsoft.com/technet/Security/prodtech/win2000/secwin2k/a0701.mspx


To delete a user from AD is pretty simple
DirectoryEntry de = new DirectoryEntry();
de.Path = ldapPath; // the user distinguishedName that to be deleted
de.User = Username; // user account which has sufficient rights to delete object in AD
de.Password = password;
entry.RefreshCache();
de.Parent.Children.Remove( de );
de.Parent.CommitChanges();


HTH
0
 
LVL 20

Expert Comment

by:ihenry
ID: 12170207

hi Nauman
any luck so far?
0
 
LVL 25

Author Comment

by:nauman_ahmed
ID: 12170327
hi ihenry,

Sorry I was bit late in replying. There is a deadline coming in two days and that stopped me working on the AD thing. I will continue working on it after 30th. So hopefully will post the response next week.

Thanks for all of your help :), Nauman.
0
 
LVL 20

Expert Comment

by:ihenry
ID: 12170494

no problem Nauman, take your time :o)
0
 

Expert Comment

by:erikking
ID: 14953708
 user.Invoke("SetPassword", new object[] {"" + newPassword + ""} );

This command does not work in Active Directory which run on Window 2003.
With an Exception error message that "The filename, directory name, or volume label syntax is incorrect."

So...Please help me..!!
0
 
LVL 25

Author Comment

by:nauman_ahmed
ID: 14957975
I have the following code that work fine in Windows 2003:

DirectoryEntry obDirEntry = new DirectoryEntry("WinNT://"+ConfigurationSettings.AppSettings["AD_SERVER_ADDR"]
                                          ,ConfigurationSettings.AppSettings["AD_ADMINISTRATOR_ID"]
                                          ,CryptoLibrary.DecryptData(ConfigurationSettings.AppSettings["AD_ADMINISTRATOR_PASSWORD"]));
DirectoryEntries entries = obDirEntry.Children;
DirectoryEntry obUser = entries.Find(UserID, "User");
obUser.Invoke("SetPassword", strUserPassword);
obUser.CommitChanges();

HTH, Nauman.
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

It seems a simple enough task, yet I see repeated questions asking how to do it: how to pass data between two forms. In this article, I will show you the different mechanisms available for you to do just that. This article is directed towards the .N…
Welcome my friends to the second instalment and follow-up to our Minify and Concatenate Your Scripts and Stylesheets (http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/A_4334-Minify-and-Concatenate-Your-Scripts-and-Stylesheets.html)…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now