Common System.DirectoryServices Issues and Solutions (READ ME FIRST).http://forums.asp.net/t/897609.aspx/1?Common+System+DirectoryServices+Issues+and+Solutions+READ+ME+FIRST+Tue, 28 Jun 2005 19:13:46 -0400897609971665http://forums.asp.net/p/897609/971665.aspx/1?Common+System+DirectoryServices+Issues+and+Solutions+READ+ME+FIRST+Common System.DirectoryServices Issues and Solutions (READ ME FIRST). <p><strong>Frequently Asked Questions:<br> </strong>---------------------------------------------</p> <p><strong>Q:&nbsp; My application works fine on my desktop, but blows up when I put it on the web.&nbsp; Why?<br> A:</strong>&nbsp; Your code runs with the same permissions as the process that executes it.&nbsp; When you run it on your desktop, it runs with YOUR credentials.&nbsp; When you run it on the web, it runs with ASPNET user or NETWORK SERVICE user (depending on platform).&nbsp; These accounts typically do not have access to AD, so access will be denied.<br> &nbsp;&nbsp;&nbsp; <br> <strong>Q:&nbsp; How can I get my code running on the web then?<br> A:</strong>&nbsp; You have a variety of options, some better than others:<br> &nbsp;&nbsp;&nbsp;&nbsp; 1. Explicitly specify credentials on the DirectoryEntry - use the constructor or .Username and .Password (don't forget your AuthenticationTypes.Secure).<br> &nbsp;&nbsp;&nbsp;&nbsp; 2. Put your code into a COM&#43; component and run it with a domain user's identity<br> &nbsp;&nbsp;&nbsp; &nbsp;3. Use delegation (&lt;identity impersonate=&quot;true&quot; /&gt;).<br> &nbsp;&nbsp;&nbsp; &nbsp;4. Run the process (IIS process or ASPNET process) as a domain user.&nbsp; This means setting an App Pool identity in IIS6 or changing the Anonymous account in IIS5 and using impersonation.<br> &nbsp;&nbsp;&nbsp; &nbsp;5. Programmatically impersonate a domain user when necessary.<br> &nbsp;<br> <strong>Q:&nbsp; Which one should I choose?<br> A:</strong>&nbsp; It depends on what you want to accomplish.&nbsp; All have their uses and are appropriate in specific situations.&nbsp; Whether or not you are allowing Anonymous access will have a bearing&nbsp;on which one you should choose as well.&nbsp; Here are some common scenarios for when each one can be appropriate:<br> &nbsp;<br> &nbsp;#1. If you are using Anonymous access or you want code to only be accessed with a single service account-like ID.&nbsp; If you are using IIS5 (XP or 2000 Server), this is not a terrible choice.&nbsp; The challenge becomes managing those credentials.&nbsp; You might need to store credentials in a config file or registry key and encrypt them using something like DPAPI.&nbsp; Once explicit&nbsp;credentials are specified, most problems go away (except for some SetPassword issues in Windows 2000).&nbsp; This is good typically for read-only type applications.&nbsp; Running with a&nbsp;more powerful account is generally not a good idea.&nbsp; If the account specified is a locked down service account, we don't have to worry about accidentally or maliciously updating&nbsp;the directory.&nbsp; If we really need to do something that updates the directory while using this technique, we should use #2, #3, or #5 in conjunction.&nbsp; I tend to prefer #4 before using this method at all, but sometimes it cannot be helped (e.g. using ADAM principals).<br> &nbsp;<br> &nbsp;#2&nbsp; This option relieves you of managing credentials by simply specifying them at deploy time in COM&#43; using the identity.&nbsp; The code will run with whatever permissions specified.&nbsp; You gain a small modicum off role based security here as well (if using Windows Authentication).&nbsp; The downside to this is that COM&#43; managed components are limited somewhat&nbsp;(no constructor, etc.), and can be a royal pain to deploy.&nbsp; Performance is not as good as other options, but typically good enough for most applications.&nbsp; This is good if you are doing a lot of Admin like functions&nbsp;where you want to let groups of users perform it without locking it to a user or giving them that permission specifically in the directory.&nbsp; It is perfectly&nbsp;acceptable to combine #1 and #5 or #4 and #5 instead of using this technique.<br> &nbsp;&nbsp;<br> &nbsp;#3&nbsp; Delegation is a powerful feature and allows us to access resources end to end with our own credentials.&nbsp; It is good when we really want people to be able to do (or not do) some function based on their inherent permissions.&nbsp; It is bad when we want groups of people to do things that they may not specifically have permission to do.&nbsp; For instance, this does not work well for helpdesk people who we typically don't want to give a bunch of permissions to, but we still want them to perform functions on our behalf.&nbsp; Using #4 and granting some of the helpdesk's necessary privileges to the service account is probably a better choice in that case.<br> &nbsp;&nbsp;<br> &nbsp;#4&nbsp; Running the process as a domain user is a lot like #1, but can be easier.&nbsp; In IIS6, this is simple using the App Pool (also add the service account to IIS_WPG group as well).&nbsp; In IIS5, this option is less appealing since we have to change the Anonymous account (IUSR_MACHINE) to a domain user and then impersonate using &lt;identity impersonate=&quot;true&quot;/&gt;.&nbsp; For IIS6, we can combine the app pool identity with Windows Authentication,&nbsp;but for IIS5, this is only appropriate for running an Anonymous site (maybe using Forms Auth).&nbsp; This is good for read-only access and some limited rights (like unlock account), but again, not a good idea if we need to update&nbsp;the directory as well.&nbsp; It can be combined with #5 for update access for more privileged tasks.&nbsp; <strong><em>Do not run websites with powerful service accounts</em></strong>.<br> &nbsp;&nbsp;<br> &nbsp;#5&nbsp; This option is typically used when we need to perform an Administrative function.&nbsp; We can temporarily impersonate an admin to perform the action and then revert back&nbsp;to a less powerful account.&nbsp; This is good for combining with #1 or #4.&nbsp; Similar to #1, the hurdle is to manage the credentials.&nbsp; It is strongly encouraged not store these credentials&nbsp;in plaintext.&nbsp; They should be encrypted using DPAPI and stored in either the registry (further ACL'd for more security), or a config file.&nbsp; Depending on the task, you might be able to use #4 with a read-only service account for most tasks and then use #1 (carefully managing credentials) for the more privileged tasks.<br> &nbsp;&nbsp;<br> <strong>Q:&nbsp; How do I get Kerberos delegation working?<br> A:</strong>&nbsp; Here are two methods to get this working for IIS applications.&nbsp; The only addition to this is that if you are using Window 2003, you should&nbsp;also combine this with constrained delegation to make sure that other resources are not being accessed.<br> &nbsp;</p> <p><em>When running with local service account (NETWORK SERVICE) App Pool</em></p> <p><em>Server-side tasks: <br> </em>&nbsp;--------------------------------------------------------------------------------- <br> &nbsp;1. IIS server must be a member of the domain and &lt;identity impersonate=&quot;true&quot;/&gt; should be in web.config<br> &nbsp;2. Set IIS server computer account in AD Users &amp; Computers MMC as &quot;Trusted for Delegation&quot; <br> &nbsp;3. IIS Server must be rebooted for this policy to take effect. <br> &nbsp;4. Integrated Windows Authentication only must be selected for site / virtual directory <br> &nbsp;5. IIS must not have NTLM only set as authentication method (this is usually not a problem, NEGOTIATE is default, so unless you specifically ran a script to change this, don't worry about it). <br> &nbsp;6. IIS server name either must match exactly account name in AD, or SetSPN tool should be used in cases where IIS site is set as alternative name (e.g. server is called server01.domain.com, and website is called <a href="http://www.application.com/">www.application.com</a>).<br> <br> <em><i>When running with Domain Service Account App Pool (i.e. #4 above)<br> </i></em></p> <p><em>Server-side tasks: <br> </em>&nbsp;--------------------------------------------------------------------------------- <br> &nbsp;1. IIS server must be a member of the domain and &lt;identity impersonate=&quot;true&quot;/&gt; should be in web.config<br> &nbsp;2. Set Domain's App Pool Identity account in AD Users &amp; Computers MMC as &quot;Trusted for Delegation&quot; <br> &nbsp;3. SetSPN must be used to add SPN to domain service account (e.g. &quot;HTTP/www.myapplication.com&quot;).<br> &nbsp;4. Integrated Windows Authentication only must be selected for site / virtual directory <br> &nbsp;5. IIS must not have NTLM only set as authentication method (this is usually not a problem, NEGOTIATE is default, so unless you specifically ran a script to change this, don't worry about it). <br> </p> <p><em>Client-side tasks <br> </em>&nbsp;--------------------------------------------------------------------------------- <br> &nbsp;1. Client must be using IE 5.x&#43;. If client is running IE 6, ensure that &quot;Enable Integrated Windows Authentication (requires restart)&quot; is selected from Tools &gt; Internet Options &gt; Advanced. <br> &nbsp;2. Web site <strong>MUST</strong> be recognized as <strong>Local Intranet</strong> (not Internet Zone) site to client. I have not seen any documentation explaining why, but I just have never been able to get it to work otherwise. If necessary, specifically add this to Local Intranet sites list. <br> &nbsp;3. Client account must not be marked as &quot;Sensitive, Do not Delegate&quot; in AD Users and Computers MMC.<br> &nbsp;<br> <strong>Q:&nbsp; How do I programmatically impersonate an Admin?<br> A:</strong>&nbsp;There are some challenges with this.&nbsp; If you are running Windows 2000, we typically need to use LogonUser api to get a token which requires giving the TCB priviledge (Act as part of the operating system).&nbsp;That, or we need to run ASPNET as SYSTEM account.&nbsp; Either way, the system is at risk here and can be owned.&nbsp; Windows 2003 and XP do not have this limitation.&nbsp; Keith Brown (<a href="http://www.pluralsight.com/">www.pluralsight.com</a>) has a sample&nbsp;on how to get a user's token from outside the TCB, which sidesteps this issue for Windows 2000 servers.<br> &nbsp;<br> &nbsp;There are sample components you can use for impersonation, here is one:<br> &nbsp;<br> &nbsp;<a href="http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=A2DC32A8-4313-4B14-9EE9-8234A8395821">http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=A2DC32A8-4313-4B14-9EE9-8234A8395821</a><br> &nbsp;<br> <strong>Q:&nbsp; I am getting errors when I run this stuff, what is the problem?<br> A:</strong>&nbsp; Have you given enough information to troubleshoot this?&nbsp; Which method (from above) are you using for access?&nbsp; Is there more than 1 domain involved or trusts?&nbsp; I have found that 90% of the issues with System.DirectoryServices code are related to security and your binding context.&nbsp; If you don't understand your context you are pretty&nbsp;screwed to begin with.&nbsp; Understand what security context your code is executing under!<br> &nbsp;<br> <strong>Q:&nbsp; I need to change a password, how do I do this?<br> A:</strong>&nbsp; If you want the user to change their own password - use 'ChangePassword'.&nbsp; If you want an Administrator to reset a password on someone's behalf, you need to use 'SetPassword'.&nbsp; Installing an SSL cert on your DC will solve almost all password change related problems.&nbsp; Without it, Kerberos or an underlying api call must be made.&nbsp; Sometimes the security&nbsp;context does not transfer and you get issues.&nbsp; Method #5 from above can help here (especially for Windows 2000).<br> &nbsp;<br> &nbsp;There is a good conversation on how to use SetPassword (and sample code) on this forum here:<br> &nbsp;<br> &nbsp;<a href="/316534/ShowPost.aspx">http://forums.asp.net/316534/ShowPost.aspx</a></p> <p><br> &nbsp;</p> 2005-06-28T19:13:46-04:00