Solved

LDAP, Web Apps, and App Pools

Posted on 2012-04-11
14
634 Views
Last Modified: 2012-04-23
I have an application that is supposed to set an AD account password.  My domain admin gave me an account that has admin access to the domain to do this.  Here's the problem:

When I try to use the application, when it tries to actually set the account password, it throws an exception indicating that it doesn't have permission to do this.  However, I know the account has admin domain privileges (I've logged in manually to this account and verified this).  

I then tried to create a separate app pool and tried to run the web site under this app pool.  I configured the app pool to use the domain admin account I was given.  When I did this, I couldn't even browse to the site - it keeps saying, "Service Unavailable'.  

When I change the app pool credentials back to the default, the web site comes up but then it doesn't work as it keeps saying I don't have permissions to change the account password.  

What am I not understanding here?  Why will this not work?
0
Comment
Question by:robertpan
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 7
14 Comments
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 37835487
How do you query the AD? There is a number of different ways to do it and there's different solutions to supply the credentials for accessing the AD, which is what you need to do (I suspect).
0
 

Author Comment

by:robertpan
ID: 37838395
This is what I am doing with regard to LDAP:

        public void ChangeUserPassword(string szUser, string szOU, string szPassword, out string szErr)
        {
            string sz = "";
            string szSID = szUser;
            string szLDAPUser = "LDAP://" + vszLDAPServer + "/CN=" + szSID + "," + szOU;

            DirectoryEntry uEntry = new DirectoryEntry(szLDAPUser, vszAdmin, vszPwd);
            uEntry.Invoke("SetPassword", new object[] { szPassword });
            uEntry.Properties["LockOutTime"].Value = 0; //unlock account
            uEntry.CommitChanges();
            uEntry.Close();

            szErr = sz;
        }

I know that that credentials used in the call (stored in vszAdmin and vszPwd) work in that I can log in manually with those credentials and change a user's password.  My admins have confirmed that those credentials do have domain admin priviledges.  

I also know that when I test it, the password I use to test meets the password strength requirements.  

I also know that when I change the call to use 'changepassword' it all works.  However, 'changepassword' will not accomplish what I need to actually do.
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 37844095
I see a number of pages when I search for 'directoryentry invoke setpassword' that seem to indicate that there are some possible problems that you can't solve 'as is' because of a bug.

One solution I came across would be to set the password like this:

uEntry.Properties["unicodePwd"].Value = System.Text.Encoding.Unicode.GetBytes(String.Format(@"""{0}""", szPassword));

Open in new window


(and remove the call to Invoke). But I'm not entirely sure if that will work in your case.
0
Guide to Performance: Optimization & Monitoring

Nowadays, monitoring is a mixture of tools, systems, and codes—making it a very complex process. And with this complexity, comes variables for failure. Get DZone’s new Guide to Performance to learn how to proactively find these variables and solve them before a disruption occurs.

 

Author Comment

by:robertpan
ID: 37844238
That did not work either - but it did generate a different exception at least:

The server is unwilling to process the request. (Exception from HRESULT: 0x80072035)


This is with the website running under the default app pool.
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 37845053
I've been trying to read up on this, finding a lot of problems but some are related to other LDAP servers like iPlanet.

It seems most reactions to an 'unwilling' server (amongst the jokes about servers having feelings like that) is that you need to use SSL to do some actions like set password which is (even in the encoded form) essentially sending a cleartext password over the network.

So you could try:

DirectoryEntry uEntry = new DirectoryEntry(szLDAPUser, vszAdmin, vszPwd, AuthenticationTypes.SecureSocketsLayer);

Open in new window


But you may need to have the server especially set up to have a secure LDAP listener (I read about port 636 instead of 389).
0
 

Author Comment

by:robertpan
ID: 37845079
Making that change results in a yet different exception:
The server is not operational.  

I guess this means I do need to set up a secure LDAP listener.  I'll see what my admins can do about this (I personally have no idea how to do this).  

One thing I did note is that my original posted code works as-is from my local machine only.  It is the *only* place the code works.  I am *not* running IIS.  I use Visual Studio to host my site when I test it.  I have no idea how VS does this so I have no idea why it would work on my local machine yet no where else.
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 37845790
The thing I read on other sites about connecting to a secure server is to use port 636 so you would need to change 'vszLDAPServer' or put it in the string for the queried user object:

string szLDAPUser = "LDAP://" + vszLDAPServer + ":636/CN=" + szSID + "," + szOU;

Open in new window


The fact that it works locally could mean that there is another solution. Could there be a difference between the two situations regarding .NET version? As far as I'm aware the current user should not have an influence on the call once you log in to the AD with a specifed account.
0
 

Author Comment

by:robertpan
ID: 37852125
This is why I'm so confused as to what is actually going on here.  The fact that it works from my local machine with a VS hosted page means I know the code itself works and the credentials are valid.  

But it won't work anywhere else.  So I don't know what IIS is doing to my request.  Do the credentials of the app pool take precedence over the supplied credentials in the actual LDAP call?  But even if so - why can I not create an app pool with those credentials?  When I do that, the web site becomes un-browsible.  When I use the default app pool the site works but the call fails.
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 37852392
> Do the credentials of the app pool take precedence over the supplied credentials in the actual LDAP call?

No, it should definitely be the other way around, as you expect. The currently logged on user (or user that the process is running under when not interactive like from the app pool) is only used to access the AD if no user is specified in the call.

> why can I not create an app pool with those credentials?

Yeah, you mentioned that. I don't think you should want that. The user is specifically created for AD access and doesn't have access to the files or lacks other permissions/policy credentials (on purpose).

* * *

I did find some slightly different code you could try:

DirectoryEntry uEntry = new DirectoryEntry(szLDAPUser, vszAdmin, vszPwd, AuthenticationTypes.Secure);

Open in new window


Secure means just logging in I think, not specifically via SSL, so if you had put in :636, take that out again.
0
 

Author Comment

by:robertpan
ID: 37852910
Nope.  

When I use this code:
            DirectoryEntry uEntry = new DirectoryEntry(szLDAPUser, vszAdmin, vszPwd, AuthenticationTypes.Secure);
            uEntry.Properties["unicodePwd"].Value = System.Text.Encoding.Unicode.GetBytes(String.Format(@"""{0}""", szPassword));

I get: The server is unwilling to process the request. (Exception from HRESULT: 0x80072035)


When I use this code:
            DirectoryEntry uEntry = new DirectoryEntry(szLDAPUser, vszAdmin, vszPwd, AuthenticationTypes.Secure);
            uEntry.Invoke("SetPassword", new object[] { szPassword });

I get Access denied.  

The site is back to running  under the default app pool.  The default app pool is running under default credentials.
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 37855583
I've been searching for that error but I'm afraid there's a number of possible reasons. Haven't gotten anywhere with digging into that because mostly it can't apply here because it works in a certain situation, from your own machine, just not from the server. Other people have found that they needed to set certain fields (mandatory from GPO), or create the user first with relaxed security, stuff like that. In your case the user already exists so that can't be the case. One thing that does stand out is someone who after several tests found out that in the end it _was_ the strict password policy that didn't accept his new password but again I can't really see how it would then work from your local machine, because that is enforced on the server.

I tried installing OpenLdap on my machine at home to see if there was any way I could reproduce it but keep getting other errors with that, before even getting back a user object...
0
 

Accepted Solution

by:
robertpan earned 0 total points
ID: 37862073
For anyone interested, I did more searching and found some code that was subtly different that worked.  

string strPort = "389";
string strPath = String.Concat("LDAP://", strServer, ":", strPort, strUser);
AuthTypes = AuthenticationTypes.Signing | AuthenticationTypes.Sealing | AuthenticationTypes.Secure;
objUser = new DirectoryEntry(strPath, vszAdmin, vszPwd, AuthTypes);
objUser.RefreshCache();

intPort = Int32.Parse(strPort);

objUser.Invoke("SetOption", new object[] { ADS_OPTION_PASSWORD_PORTNUMBER, intPort });
objUser.Invoke("SetOption", new object[] {ADS_OPTION_PASSWORD_METHOD, ADS_PASSWORD_ENCODE_CLEAR});
objUser.Invoke("SetPassword", new object[] { szPassword });

This code is not hugely different than my original code - but this works.
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 37862178
Fair enough, no objection. Thanks for sharing. Might save someone else some time some day.
0
 

Author Closing Comment

by:robertpan
ID: 37879986
It solved the problem.
0

Featured Post

Forrester Webinar: xMatters Delivers 261% ROI

Guest speaker Dean Davison, Forrester Principal Consultant, explains how a Fortune 500 communication company using xMatters found these results: Achieved a 261% ROI, Experienced $753,280 in net present value benefits over 3 years and Reduced MTTR by 91% for tier 1 incidents.

Question has a verified solution.

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

This article shows the method of using the Resultant Set of Policy Tool to locate Group Policy that applies a particular setting.
Recently, Microsoft released a best-practice guide for securing Active Directory. It's a whopping 300+ pages long. Those of us tasked with securing our company’s databases and systems would, ideally, have time to devote to learning the ins and outs…
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.

726 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