Exchange Server TechCenter > Exchange Server Forums > Development > Active Directory (ADAM) on Windows Server 2000 SP4 .Net 1.1 does not work
Ask a questionAsk a question
 

AnswerActive Directory (ADAM) on Windows Server 2000 SP4 .Net 1.1 does not work

  • Monday, October 20, 2008 2:51 AMShailen Sukul Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    I am working for a large banking client who have older infrastructure in the Application services layer.

     

    I have created a COM+ component that resides in an Application server with the following specs:

    * Windows Server 2000 SP4

    * .Net Framework 1.1

    * has its own workgroup

     

    This component communicates to an ADAM (AD) server with the following specs:

    * Windows Server 2003 Standard Edition R2 (5.2.3790)

     

    To remove any COM+ complexity, I have created a simple .Net Windows application to test the ADAM calls.

     

    When I call ResetPassword from my XP SP2 machine, it works as does the test from another Windows Server 2003 R2 machine on the domain.

     

    When I move the same binary to the Windows 2000 box, the ResetPassword call DOES NOT work. I have another method called IsValid that takes in a user id and password and validates it in ADAM. IsValid WORKS on the Windows 2000 box.

     

    I raised a call with a Microsoft representative and they have been able to replicate this issue on their environments.

     

    After debugging code, I have observed that the bind to ADAM works. It only breaks when ResetPassword is called and only from Windows 2000.

     

    I have spent close to a week going to and fro with Microsoft and still do not have a resolution.

    I think it could be one of the following:

    - A bug with .Net framework 1.1 on Windows 2000

    - Incorrect code on my part

    - Incorrect setup of ADAM

     

    Here why I think it may be a Microsoft bug:

    - the code WORKS from other non-Windows 2000 machines

    - I am using AD PwdReset code from MSDN (http://msdn.microsoft.com/en-us/library/aa772136.aspx) which has been verified by Microsoft (with a minor tweak, see code below where the invoke arguments are explicitly cast to object)

     

    =========================================================================

    Here is the ResetPassword code:

    Code Snippet

    public Response ResetPassword(User user, string newPassword, bool useSSL) {

    Response response;

    try {

    AuthenticationTypes authTypes = (useSSL ? (AuthenticationTypes.None | AuthenticationTypes.SecureSocketsLayer) :  (AuthenticationTypes.None));

     

      Trace.WriteLine("===============================================================");

      Trace.WriteLine(string.Format("Authentication format is : {0}", authTypes.ToString()));

      Trace.WriteLine("===============================================================");

      Trace.Flush();

     

      // Bind to user object using LDAP port.

      // GetOrgUrl = LDAP://m01:50008/CN=Users,CN=org1

      using (DirectoryEntry entry = new DirectoryEntry(GetOrgUrl(useSSL),

                          _adminUser, _adminPwd, authTypes)) {                                                                  

                                                   

     Trace.WriteLine("===============================================================");

    Trace.WriteLine(string.Format("LDAP Top Level Path for ResetPasswod (SSL) function is: {0}", OrgUrl(useSSL)));

     Trace.WriteLine("===============================================================");

     Trace.Flush();

     entry.RefreshCache();

                                                   

     Trace.WriteLine("===============================================================");

     Trace.WriteLine(string.Format("Successfully bound to: {0}", GetOrgUrl(useSSL)));

     Trace.WriteLine("===============================================================");

     Trace.Flush();

     

    /* Find the user */

    using (DirectorySearcher ds = new DirectorySearcher(entry)) {

    ds.SearchScope = SearchScope.Subtree;

    ds.Filter = "(&(objectclass=*)(cn= " + user.UserName + "))";

    SearchResult sr;                                         

    sr = ds.FindOne();

    if (sr != null) {

    using (DirectoryEntry de = new DirectoryEntry(sr.Path, _adminUser, _adminPwd, authTypes)) {

     

     Trace.WriteLine("===============================================================");

     Trace.WriteLine(string.Format("Binding to user path: {0} using authentication type: {1}",

                                                                       sr.Path, authTypes));

     Trace.WriteLine("===============================================================");

     Trace.Flush();

     

     de.RefreshCache();

     

     Trace.WriteLine("===============================================================");

     Trace.WriteLine("Invoking ResetPassword ...");

     Trace.WriteLine("===============================================================");

     Trace.Flush();

     

    //Reset password throws an exception here while running on Windows Server 2000

    de.Invoke("SetOption", new object[] {(int)ADS_OPTION_PASSWORD_PORTNUMBER, (object)_portNo });                                                                     

    de.Invoke("SetOption", new object[] { (int)ADS_OPTION_PASSWORD_METHOD, (object)ADS_PASSWORD_ENCODE_CLEAR});                                                                          

    de.Invoke("SetPassword", new object[] {newPassword});                                                                       

     

    response = new Response();

    response.IsSuccess = true;

    response.Data = "TRUE";                        

    }}

    else {

    Trace.WriteLine("=======================================================================");

    Trace.WriteLine(string.Format("User {0} not found", user.UserName));

    Trace.WriteLine("=======================================================================");

    Trace.Flush();

    response = new Response();

    response.IsSuccess = false;

    response.FriendlyMessage = string.Format("ResetPassword call failed for user {0}", user.UserName);

    response.Message = string.Format("User {0} does not exist.", user.UserName);

    response.Data = "FALSE";

                                                              }}}}

    catch (System.Reflection.TargetInvocationException tEx) {

      response = GetError(tEx);

      response.FriendlyMessage = string.Format("ResetPassword call failed for user {0}", user.UserName);

      response.Data = "FALSE";

    }

    catch (Exception ex) {

    response = GetError(ex);

    response.FriendlyMessage = string.Format("ResetPassword call failed for user {0}", user.UserName);

    response.Data = "FALSE"; }

    return response; }

     

     

     

    Here is the error message that I get:

     

    ResetPasswordNonSSL() called.

    Response

    ===========

    IsSuccess: False

    Data: FALSE

    Friendly Message:ResetPassword call failed for user user1

     Message: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Runtime.InteropServices.COMException (0x80005008): Exception from HRESULT: 0x80005008.

       --- End of inner exception stack trace ---

       at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)

       at System.RuntimeType.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters)

       at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args)

       at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args)

       at ADAM.ADAMHelper.ResetPassword(User user, String newPassword, Boolean useSSL)

    Stack Trace:   at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)

       at System.RuntimeType.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters)

       at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args)

       at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args)

       at ADAM.ADAMHelper.ResetPassword(User user, String newPassword, Boolean useSSL)

    ======================================================================================

    Authentication format is : None

    ======================================================================================

    LDAP Top Level Path for ResetPasswod (SSL) function is: LDAP://m01:50008/CN=Users,CN=org1

    ======================================================================================

    ======================================================================================

    Successfully bound to: LDAP://m01:50008/CN=Users,CN=org1

    ======================================================================================

    ======================================================================================

    Binding to user path: LDAP://m01:50008/CN=user1,CN=Users,CN=org1 using authentication type: None

    ======================================================================================

    ======================================================================================

    Invoking ResetPassword ...

    ======================================================================================


     

     

Answers

  • Monday, October 20, 2008 5:42 AMShailen Sukul Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

     

    This issue has been resolved !!!

     

    I had to apply a Hotfix on the Windows 2000 machine that was calling ADAM.

     

    See this url:

    http://support.microsoft.com/kb/817583

     

    The principal cause was the following:

    "This problem occurs because ADSI is restricted to SSL port number 636 when it makes a bind call to the LDAP server."

All Replies

  • Monday, October 20, 2008 5:42 AMShailen Sukul Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

     

    This issue has been resolved !!!

     

    I had to apply a Hotfix on the Windows 2000 machine that was calling ADAM.

     

    See this url:

    http://support.microsoft.com/kb/817583

     

    The principal cause was the following:

    "This problem occurs because ADSI is restricted to SSL port number 636 when it makes a bind call to the LDAP server."