Solved

LDAP, Web Apps, and App Pools

Posted on 2012-04-11
14
635 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
U.S. Department of Agriculture and Acronis Access

With the new era of mobile computing, smartphones and tablets, wireless communications and cloud services, the USDA sought to take advantage of a mobilized workforce and the blurring lines between personal and corporate computing resources.

 

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

How our DevOps Teams Maximize Uptime

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us. Read the use case whitepaper.

Question has a verified solution.

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

A project that enables an administrator to perform actions within a user session context not just at the time of login but any time later on day(s) or week(s) later.
After seeing many questions for JRNL_WRAP_ERROR for replication failure, I thought it would be useful to write this article.
This tutorial will walk an individual through the process of configuring their Windows Server 2012 domain controller to synchronize its time with a trusted, external resource. Use Google, Bing, or other preferred search engine to locate trusted NTP …
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …

728 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