Solved

LDAP, Web Apps, and App Pools

Posted on 2012-04-11
14
630 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
  • 7
  • 7
14 Comments
 
LVL 35

Expert Comment

by:Robert Schutt
Comment Utility
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
Comment Utility
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
Comment Utility
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
 

Author Comment

by:robertpan
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:robertpan
Comment Utility
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
Comment Utility
> 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Fair enough, no objection. Thanks for sharing. Might save someone else some time some day.
0
 

Author Closing Comment

by:robertpan
Comment Utility
It solved the problem.
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Prologue It is often required to host multiple websites on a single instance of IIS, mostly in development environments instead of on production servers. I am sure it is not much a preferred solution on production servers but this is at least a pos…
Resolve DNS query failed errors for Exchange
This tutorial will walk an individual through the steps necessary to join and promote the first Windows Server 2012 domain controller into an Active Directory environment running on Windows Server 2008. Determine the location of the FSMO roles by lo…
This tutorial will walk an individual through the process of transferring the five major, necessary Active Directory Roles, commonly referred to as the FSMO roles to another domain controller. Log onto the new domain controller with a user account t…

771 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

10 Experts available now in Live!

Get 1:1 Help Now