<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>gyanjadaloldblogs</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/active_directory_cross_forest_member_extraction_using_c/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/active_directory_cross_forest_member_extraction_using_c/feed.xml</link>
    <description>My soft(ware) corner</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:37:27 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Extract user details across Active Directory forests using C#</title>
      <link>https://docs.microsoft.com/archive/blogs/active_directory_cross_forest_member_extraction_using_c/extract-user-details-across-active-directory-forests-using-c</link>
      <pubDate>Fri, 22 Oct 2010 13:19:00 GMT</pubDate>
      <dc:creator><![CDATA[Gyan Jadal]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/active_directory_cross_forest_member_extraction_using_c/2010/10/22/extract-user-details-across-active-directory-forests-using-c/</guid>
      <description><![CDATA[This post describes how to retrieve member details from a Security group that has members from...]]></description>
      <content:encoded><![CDATA[<p>This post describes how to retrieve member details from a Security group that has members from different forests.</p>
<p>Lets consider the following example:</p>
<p><em>Security Group name : mydomain\secureSG&nbsp; ( let say this resides in forest 'myforest')</em></p>
<p>Lets say the following members exist in the above security group,</p>
<p>mydomain\john&nbsp; (this user belongs to the&nbsp;'myforest' same as the SG and to the same domain 'mydomain')</p>
<p>otherdomain\bob&nbsp; (this user belongs to the&nbsp;'myforest' same as the SG but&nbsp;to&nbsp;a&nbsp;different domain 'otherdomain')</p>
<p>someotherdomain\tom&nbsp; (this user belongs to a different forest altogether, lets say 'otherforest' and a&nbsp;domain called 'someotherdomain' in that forest)</p>
<p>Now, considering the above scenario, if&nbsp;we want to fetch all the members alias of the above security group we can do the following,</p>
<p>&nbsp;<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span></p>
<pre class="scroll" style="PADDING-LEFT: "><code class="csharp">string rootDomain = "LDAP://DC=mydomain,DC=myforest,DC=company,DC=com";
<br />
<br />DirectoryEntry domainEntry = new DirectoryEntry(rootDomain);

 <br />DirectorySearcher search = new DirectorySearcher(domainEntry);
<br />
<br />search.Filter = "(cn=secureSG)";
<br />
<br />search.PropertiesToLoad.Add("member");
<br />
<br />SearchResult result = search.FindOne();
<br />
<br />if (null != result &amp;&amp; result.Properties["member"].Count &gt; 0)
<br />
<br />{
<br />
<br />DirectoryEntry gpMemberEntry = null;
<br />
<br />for (int counter = 0; counter &lt; result.Properties["member"].Count; counter++)
<br />
<br />{
<br />
<br />object currentMember = result.Properties["member"][counter];
<br />
<br />gpMemberEntry = new DirectoryEntry("LDAP://" + currentMember);
<br />
<br />string userAlias = gpMemberEntry.Properties["sAMAccountName"].Value as string;
<br />
<br />Console.WriteLine(userAlias);
<br />
<br />}
<br />
<br />}
<br />
</code></pre>
<p>Doing this would return the&nbsp;alias for the first 2 members correctly, in this case 'john' and 'bob'.</p>
<p>However, in case of tom, the userAlias would be null. </p>
<p>ie. The output will be</p>
<p>'john'</p>
<p>'bob'</p>
<hr width="200" style="text-align: left; width: 200px;" />
<p>&nbsp;</p>
<p>To extract the userAlias for tom, we would need to perform the following steps</p>
<p style="PADDING-LEFT: 30px"><em><span style="color: #666699;"><span style="color: #000000;">1. Extract the SID from the member object</span></span></em></p>
<p style="PADDING-LEFT: 30px"><em><span style="color: #666699;"><span style="color: #000000;">2. Create a SecurityIdentifier object from the SID</span></span></em></p>
<p style="PADDING-LEFT: 30px"><em><span style="color: #666699;"><span style="color: #000000;">3. Translate the SID into an NTAccount.</span></span></em></p>
<p style="PADDING-LEFT: 30px"><em><span style="color: #666699;"><span style="color: #000000;">4. Get the userAlias from the NTAccount object.</span></span></em></p>
<p><em><span style="color: #666699;"><strong>PS: What is a Security ID (SID).</strong> Active Directory automatically assigns SIDs to security principal objects at the time they are created. Security principals are accounts in Active Directory that can be assigned permissions such as computer, group, or user accounts. Once a SID is issued to the authenticated user, it is attached to the access token of the user.<br /></span></em><br />Following is the updated&nbsp;implementation of our sample&nbsp;above,</p>
<p>&nbsp;</p>
<pre class="scroll"><code class="csharp">string rootDomain = "LDAP://DC=mydomain,DC=myforest,DC=company,DC=com";
<br />
<br />        DirectoryEntry domainEntry = new DirectoryEntry(rootDomain);
<br />        
<br />        DirectorySearcher search = new DirectorySearcher(domainEntry);
<br />        search.Filter = "(cn=secureSG)";
<br />        search.PropertiesToLoad.Add("member");
<br />
<br />        SearchResult result = search.FindOne();
<br />
<br />        if (null != result &amp;&amp; result.Properties["member"].Count &gt; 0)
<br />        {
<br />            DirectoryEntry gpMemberEntry = null;
<br />
<br />            for (int counter = 0; counter &lt; result.Properties["member"].Count; counter++)
<br />            {
<br />                object currentMember = result.Properties["member"][counter];
<br />                gpMemberEntry = new DirectoryEntry("LDAP://" + currentMember);
<br />                string userAlias = gpMemberEntry.Properties["sAMAccountName"].Value as string;
<br />                <span style="background-color: #ffff99;">if (string.IsNullOrEmpty(userAlias))
<br />                {
<br />                    string sid = gpMemberEntry.Properties["cn"].Value.ToString();
<br />
<br />                    IdentityReference id = new SecurityIdentifier(sid);
<br />                    string[] account = id.Translate(typeof(NTAccount)).ToString().Split('\\');                }
<br />                    userAlias = account[1];   
<br />                }
<br /></span>                Console.WriteLine(userAlias);
<br />            }
<br />        }</code></pre>
<p>&nbsp;</p>
<p>The output will now be</p>
<p>'john'</p>
<p>'bob'</p>
<p>'tom'</p>
<p>&nbsp;</p>
<p>Hope this helps..</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
  </channel>
</rss>