A web part I developed needed to access Active Directory. A lot of posts say to just set the site’s trust level to Full, but that is a security risk.
The solution I found was to use a wss_custom trust level.
First, I copied the wss_minimal.config file in the CONFIG file of the 14-hive and named it wss_custom.config.
I then modified it as described in this post: http://www.derkeiler.com/Newsgroups/microsoft.public.dotnet.security/2004-10/0240.html
I added this to <SecurityClasses>:
< SecurityClass Name=”DirectoryServicesPermission” Description=”System.DirectoryServices.DirectoryServicesPermission, System.DirectoryServices, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”/>
Then I added the “DirectoryServicesPermission” to the “NamedPermissionSet” of “ASP.NET”:
<PermissionSet class=”NamedPermissionSet” version=”1″ Name=”ASP.Net”>
<IPermission class=”DirectoryServicesPermission” version=”1″ Unrestricted=”true”/>
</PermissionSet>
[Note: I didn’t remove the other entries in those two sections.]
In the web.config file, I added this to the <securityPolicy> settings:
<trustLevel name=”WSS_Custom” policyFile=”C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\config\wss_custom.config” />
Next, I changed the trust level in the web.config file to WSS_Custom.
<trust level=”WSS_Custom” originUrl=”” />
[In addition to the post referenced above, this post helped me understand the steps to use a customized Code Access Security policy: http://blog.tylerholmes.com/2008/11/creating-custom-cas-policy-file-for.html]
In my web part C# code, I used PrincipalContext with a user with appropriate AD permissions:
PrincipalContext cxt = new PrincipalContext(ContextType.Domain, sDomain, sUser, sPwd);
using (UserPrincipal user = UserPrincipal.FindByIdentity(cxt, sAccountName))
{
DirectoryEntry entry = user.GetUnderlyingObject() as DirectoryEntry;
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.PropertiesToLoad.Add(“proxyAddresses”);
searcher.Filter = “(&(objectClass=user)(|(sAMAccountName=” + sAccountName + “)))”;
SearchResult result = searcher.FindOne();
if (result == null)
{
litResult.Text += “Error: User not found.”;
}
else
{
//do something
}
}
entry.Close();
entry.Dispose();
searcher.Dispose();
cxt.Dispose();