Solved

Change Active Directory User Password method SetPassword and ASP.Net

Posted on 2004-09-20
13
2,232 Views
Last Modified: 2008-03-17
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
  • 7
  • 5
13 Comments
 
LVL 25

Author Comment

by:nauman_ahmed
ID: 12104502
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 17

Expert Comment

by:AerosSaga
ID: 12104720
try this:

      
Joe Kaplan \(MVP - ADSI\) (VIP)
Ok, I see. Here are the steps to accomplish that:

1. Bind to the directory root with with the user's current name and password
to get the domain search root
2. Find the user by their username in the directory using the
DirectorySearcher
3. Bind the user's DirectoryEntry (found from 2)
4. Invoke the ChangePassword method (not the SetPassword method, since that
is used by admins to reset a password)

Here is some sample code that should come close to what you are trying to
do. I wasn't able to test this, and you may need to modify it based on your
DC name and also on the type of encryption you are going to use (SSL or
Kerberos).

Private Sub ChangePassword(ByVal username As String, ByVal oldPassword
As String, ByVal newPassword As String)

Dim dcDNS As String = "yourdc.com" 'use this if you want to supply a
server name
Dim rootDN As String
Dim rootDSE As DirectoryEntry
Dim searchRoot As DirectoryEntry
Dim userEntry As DirectoryEntry
Dim searcher As DirectorySearcher
Dim results As SearchResultCollection
Dim result As SearchResult

Try
'note the authenicationtypes here
'you need to either use SecureSocketsLayer or Kerberos (Secure +
Sealing)
rootDSE = New DirectoryEntry(String.Format("LDAP://{0}/rootDSE",
dcDNS), username, oldPassword, AuthenticationTypes.Secure Or
AuthenticationTypes.Sealing Or AuthenticationTypes.ServerBind)
rootDN =
DirectCast(rootDSE.Properties("defaultNamingContext").Value, String)
searchRoot = New DirectoryEntry(String.Format("LDAP://{0}/{1}",
dcDNS, rootDN), username, oldPassword, AuthenticationTypes.Secure Or
AuthenticationTypes.Sealing Or AuthenticationTypes.ServerBind)
searcher = New DirectorySearcher(searchRoot)
searcher.Filter = String.Format("sAMAccountName={0}", username)
searcher.SearchScope = SearchScope.Subtree
searcher.CacheResults = False

'I use FindAll here because FindOne leaks memory if it does not
find anything
'in .NET 1.0 and 1.1
results = searcher.FindAll()
For Each result In results
'only use this method on .NET 1.1 or higher
'otherwise, get the adsPath value and build a new
DirectoryEntry with the supplied credentials
userEntry = result.GetDirectoryEntry()
Exit For 'this is redundant because sAMAccountName is unique
in the domain, but it is done for clarity
Next

If userEntry Is Nothing Then
Throw New InvalidOperationException("User not found in this
domain.")
End If

userEntry.Invoke("ChangePassword", New Object() {oldPassword,
newPassword})
userEntry.CommitChanges()

Catch ex As System.Reflection.TargetInvocationException
Throw ex.InnerException

Finally 'these prevent other memory leaks
If Not userEntry Is Nothing Then userEntry.Dispose()
If Not results Is Nothing Then results.Dispose()
If Not searcher Is Nothing Then searcher.Dispose()
If Not searchRoot Is Nothing Then searchRoot.Dispose()
If Not rootDSE Is Nothing Then rootDSE.Dispose()
End Try
End Sub

You may need to experiment with different variations on the dcDNS variable
and you may need to remove the ServerBind flag if you are using a NETBIOS
name. Also, you may need to remove the Sealing flag as well, but be warned
that in order to set or change passwords, some sort of encrypted channel
(SSL or Kerberos) must be available.

Regards,

Aeros
0
 
LVL 17

Expert Comment

by:AerosSaga
ID: 12104751
0
Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

 
LVL 25

Author Comment

by:nauman_ahmed
ID: 12104769
Thanks Aeros.

ChangePassword is working fine at my side. The problem is with SetPassowrd.

-Nauman.
0
 
LVL 17

Expert Comment

by:AerosSaga
ID: 12104800
IIS 5.0 or 6.0?
0
 
LVL 25

Author Comment

by:nauman_ahmed
ID: 12104894
I tried on both :(

-Nauman.
0
 
LVL 17

Expert Comment

by:AerosSaga
ID: 12104958
same result?
0
 
LVL 25

Author Comment

by:nauman_ahmed
ID: 12104999
yeah. Its all the same and no luck until now.

-Nauman.
0
 
LVL 17

Accepted Solution

by:
AerosSaga earned 500 total points
ID: 12105013
try it this way then:

private void AddUser(string strDoamin, string strLogin, string strPwd)
{
      DirectoryEntry obDirEntry = null;
      try
      {
            obDirEntry = new DirectoryEntry("WinNT://" + strDoamin);
            DirectoryEntries entries = obDirEntry.Children;
            DirectoryEntry obUser = entries.Add(strLogin, "User");
            obUser.Properties["FullName"].Add("Amigo");
            object obRet = obUser.Invoke("SetPassword", strPwd);
            obUser.CommitChanges();
      }
      catch (Exception ex)
      {
            Trace.Warn(ex.Message);
      }
}

0
 
LVL 25

Author Comment

by:nauman_ahmed
ID: 12105405
thanks aeros.. It is working with WINNT prefix. But one thing that I will never understand is why we have to tame windows instead of using the methods that have been already defined in MSDN? I have been working on this since 2 days but didnt have any luck. Thanks a lot again..and if there is an explanation of using WinNT instead of LDAP prefix, please post it here.

Thanks, Nauman.
0
 
LVL 17

Expert Comment

by:AerosSaga
ID: 12105449
You must have noticed from the above list that there is no property to set or get user password value. Operating system does not give access to clear text password value. So we can't expect and property or method to get it. In ADSI,  IAdsUser interface provides SetPassword method to set a user's password. This is where Invoke method of DirectoryEntry  class comes handy. So we call Invoke to set the password value. The Invoke method can be used to call native methods on underlying active directory objects. There is one important thing to remeber when you set a user's password value. If you are using LDAP provider, then the user account should already have been created in the system by calling CommitChanges  or SetInfo method. But WinNT provider does not have this restriction. You can set password value without commiting the changes first.

http://www.netomatix.com/AddNewUser.aspx

Regards,

Aeros
0
 
LVL 17

Expert Comment

by:AerosSaga
ID: 12105530
Glad I could be of some assistance to you my friend.

Aeros
0
 

Expert Comment

by:erikking
ID: 14953478

entry.Invoke("SetPassword",new object[] {"testing"});

This command does not work in Active Directory which run on Window 2003. With error message that "Type mismatch."
So...Please help me..!!
0

Featured Post

Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

One of the pain points with developing AJAX, JavaScript, JQuery, and other client-side behaviors is that JavaScript doesn’t allow for cross domain request for pulling content. For example, JavaScript code on www.johnchapman.name could not pull conte…
Problem Hi all,    While many today have fast Internet connection, there are many still who do not, or are connecting through devices with a slower connect, so light web pages and fast load times are still popular.    If your ASP.NET page …
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…

828 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