Re: DirectorySearcher - SearchResult - User Groups

From: George Durzi (gdurzi_at_hotmail.com)
Date: 12/17/04


Date: Thu, 16 Dec 2004 20:36:15 -0700

Thanks for all the tips and help Joe. I'll definitely incorporate those
suggestions to close those gaps in the code.

Thank You

"Joe Kaplan (MVP - ADSI)" <joseph.e.kaplan@removethis.accenture.com> wrote
in message news:%23Pdssf64EHA.3648@TK2MSFTNGP11.phx.gbl...
> Sounds good. One thing to be careful about is that your code looks like
> it tries to parse the CN out of the distinguished name of the group and
> return that. Be aware that AD can have duplicate CNs (as long as the
> objects are in different containers in the hierarchy), so you can get into
> a lot of trouble using that for security decisions. Also, I don't think
> you code will handle "," characters that are escaped with a \ in the CN
> which, could cause your parsing to fail.
>
> That's another reason I hate that sample from kbase. The security
> practices it suggests are not very sound at all.
>
> Joe K.
>
> "George Durzi" <gdurzi@hotmail.com> wrote in message
> news:elTzSD54EHA.3596@TK2MSFTNGP12.phx.gbl...
>> Joe,
>> I looked up tokenGroups, and they definitely look like a better way to
>> determine group membership. In the meantime, I've gotten my othercode to
>> work.
>>
>> I consolidated the authentication, and the membership checking into the
>> same function. Because, as you mentioned, the second search isn't really
>> necessary at all.
>>
>> Here's my function:
>>
>> public string IsAuthenticatedGetGroups (string Domain, string UserName,
>> string Password)
>> {
>> string sGroups = string.Empty;
>> string DomainUserName = string.Concat(Domain, @"\", UserName);
>> try
>> {
>> DirectoryEntry oDE = new DirectoryEntry(
>> _path, // LDAP Connect String
>> DomainUserName, // User
>> Password, // Password
>> AuthenticationTypes.Secure); // Authentication Type
>>
>> Object oNativeObject = oDE.NativeObject;
>> DirectorySearcher oDS = new DirectorySearcher(oDE);
>>
>> oDS.Filter = string.Concat("(&(objectClass=user)(SAMAccountName=",
>> UserName, "))");
>> oDS.PropertiesToLoad.Add("CN");
>> oDS.PropertiesToLoad.Add("memberOf");
>>
>> SearchResult oSR = oDS.FindOne();
>> if (null == oSR)
>> return string.Empty;
>> else
>> {
>> if (oSR.Properties["memberOf"] == null)
>> return string.Empty;
>> else
>> {
>> int iPropertyCount = oSR.Properties["memberOf"].Count;
>> StringBuilder sbGroupNames = new StringBuilder();
>>
>> string dn;
>> int equalsIndex, commaIndex;
>>
>> for (int i = 0; i < iPropertyCount; i++)
>> {
>> dn = (string)oSR.Properties["memberOf"][i];
>> equalsIndex = dn.IndexOf("=", 1);
>> commaIndex = dn.IndexOf(",", 1);
>>
>> if (-1 == equalsIndex) return string.Empty;
>>
>> sbGroupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex -
>> equalsIndex) - 1));
>> sbGroupNames.Append("|");
>> }
>> sGroups = sbGroupNames.ToString();
>> }
>> }
>>
>> }
>> catch (Exception)
>> {
>> return string.Empty;
>> }
>> return sGroups;
>> }
>>
>> "Joe Kaplan (MVP - ADSI)" <joseph.e.kaplan@removethis.accenture.com>
>> wrote in message news:eInuyX44EHA.2608@TK2MSFTNGP10.phx.gbl...
>>> You probably want the DN for your search root to be the domain root,
>>> which is likely to be:
>>> DC=corp,DC=isacorp,DC=com
>>>
>>> The search below uses the actual user's DN (making the search not really
>>> necessary at all), so it would need to be base-level if you were going
>>> to do that.
>>>
>>> That said, I don't recommend the approach suggested by that article for
>>> getting group membership. I think you should consider using tokenGroups
>>> instead to discover security group membership. If you do some Google
>>> groups searches on tokenGroups, you should see some samples.
>>>
>>> Joe K.
>>>
>>> "George Durzi" <gdurzi@hotmail.com> wrote in message
>>> news:OVaffC44EHA.1596@tk2msftngp13.phx.gbl...
>>>> Hi,
>>>> I'm having trouble fetching the AD groups a user belongs to after
>>>> authenticating them against Active Directory. My code is based on the
>>>> How To for using Forms Authentication to authenticate against AD
>>>> (http://support.microsoft.com/default.aspx?scid=kb;en-us;326340)
>>>>
>>>> LDAP ConnectString:
>>>> LDAP://VN-SRV-DC01.corp.isacorp.com/DC=corp,DC=isacorp,DC=com
>>>> Domain Name: VN-SRV-DC01.corp.isacorp.com
>>>>
>>>> Initially, when I use the DirectorySearcher to find cn=gdurzi, the path
>>>> of the results is:
>>>> LDAP://VN-SRV-DC01.corp.isacorp.com/CN=gdurzi,CN=Users,DC=corp,DC=isacorp,DC=com
>>>>
>>>> My code does the following to get the users groups does the following:
>>>>
>>>> DirectorySearcher oDS = new
>>>> DirectorySearcher("LDAP://VN-SRV-DC01.corp.isacorp.com/CN=gdurzi,CN=Users,DC=corp,DC=isacorp,DC=com");
>>>> oDS.Filter ="(cn=gdurzi)";
>>>> oDS.PropertiesToLoad.Add("memberOf");
>>>> try {
>>>> SearchResult oSR = oDS.FindOne();
>>>>
>>>> I get an Exception on the call to FindOne. "The specified domain either
>>>> does not exist or could not be contacted"
>>>>
>>>> After binding to the VN-SRV-DC01.corp.isacorp.com domain in ldp.exe, I
>>>> can do a search for cn=gdurzi successfully by using a Base DN of:
>>>> CN=Users,DC=corp,DC=isacorp,DC=com
>>>>
>>>> ***Searching...
>>>> ldap_search_s(ld, "CN=Users,DC=corp,DC=isacorp,DC=com", 1, "CN=gdurzi",
>>>> attrList, 0, &msg)
>>>> Result <0>: (null)
>>>> Matched DNs:
>>>> Getting 1 entries:
>>>>>> Dn: CN=gdurzi,CN=Users,DC=corp,DC=isacorp,DC=com
>>>> 4> objectClass: top; person; organizationalPerson; user;
>>>> 1> cn: gdurzi;
>>>> 1> distinguishedName: CN=gdurzi,CN=Users,DC=corp,DC=isacorp,DC=com;
>>>> 1> name: gdurzi;
>>>> 1> canonicalName: corp.isacorp.com/Users/gdurzi;
>>>>
>>>>
>>>> If I open the enterprise tree in ldp.exe and find my cn, here's what I
>>>> get:
>>>>
>>>> Expanding base 'CN=gdurzi,CN=Users,DC=corp,DC=isacorp,DC=com'...
>>>> Result <0>: (null)
>>>> Matched DNs:
>>>> Getting 1 entries:
>>>>>> Dn: CN=gdurzi,CN=Users,DC=corp,DC=isacorp,DC=com
>>>> 4> objectClass: top; person; organizationalPerson; user;
>>>> 1> cn: gdurzi;
>>>> 1> sn: Durzi;
>>>> 1> givenName: George;
>>>> 1> distinguishedName: CN=gdurzi,CN=Users,DC=corp,DC=isacorp,DC=com;
>>>> 1> instanceType: 4;
>>>> 1> whenCreated: 11/24/2004 22:38:51 US Mountain Standard Time US
>>>> Mountain Standard Time;
>>>> 1> whenChanged: 12/16/2004 7:58:12 US Mountain Standard Time US
>>>> Mountain Standard Time;
>>>> 1> displayName: George Durzi;
>>>> 1> uSNCreated: 8471;
>>>> 2> memberOf: CN=FrameworkAdmins,CN=Users,DC=corp,DC=isacorp,DC=com;
>>>> CN=Remote Desktop Users,CN=Builtin,DC=corp,DC=isacorp,DC=com;
>>>> 1> uSNChanged: 349743;
>>>> 1> name: gdurzi;
>>>> 1> objectGUID: 2975a92e-fb4b-4141-a0de-482dca83d95b;
>>>> 1> userAccountControl: 0x10200;
>>>> 1> badPwdCount: 0;
>>>> 1> codePage: 0;
>>>> 1> countryCode: 0;
>>>> 1> badPasswordTime: <ldp error <0x0>: cannot format time field;
>>>> 1> lastLogon: <ldp error <0x0>: cannot format time field;
>>>> 1> logonHours: <ldp: Binary blob>;
>>>> 1> pwdLastSet: <ldp error <0x0>: cannot format time field;
>>>> 1> primaryGroupID: 513;
>>>> 1> userParameters: m: d ;
>>>> 1> objectSid: S-1-5-21-1561616353-131408304-1539857752-1612;
>>>> 1> accountExpires: 0;
>>>> 1> logonCount: 12;
>>>> 1> sAMAccountName: gdurzi;
>>>> 1> sAMAccountType: 805306368;
>>>> 1> userPrincipalName: gdurzi;
>>>> 1> objectCategory:
>>>> CN=Person,CN=Schema,CN=Configuration,DC=corp,DC=isacorp,DC=com;
>>>> 1> msNPAllowDialin: TRUE;
>>>> -----------
>>>>
>>>> You can see that the memberOf property properly pulls the groups my cn
>>>> is a member of:
>>>>
>>>> memberOf: CN=FrameworkAdmins,CN=Users,DC=corp,DC=isacorp,DC=com;
>>>> CN=Remote Desktop Users,CN=Builtin,DC=corp,DC=isacorp,DC=com;
>>>>
>>>>
>>>> Any idea why my code is error'ing at the call to FindOne?
>>>>
>>>
>>>
>>
>>
>
>



Relevant Pages