LDAP property contains to many values - c#

I have a function witch tries to remove a member from a group
The problem is if you try to remove a member, without knowing the existence in the group, you could cause an exception.
So I try to enumerate its membership beforehand.
The problem now is that the member property stops after 3000 Entries, and I don't know a way to get more, or the next 3000 members of that group.
Here is my code
DirectoryEntry target_group = new DirectoryEntry(LDAP_group_DN);
if (target_group.Properties["member"].Contains(LDAP_member_to_remove_DN)) {
target_group.Properties["member"].Remove(LDAP_member_to_remove_DN);
}
target_group.CommitChanges();
target_group.Properties["member"] contains exactly 3000 entries, but in reality it is around 7500.
As a shorthand fix I am using the remove statement in a try/catch block without the .Contains() check, but that doesn't seem correct/beautiful/right.
Can anyone lead me to the correct way?
PS: I can not change the structure of our Directory.
This is a Group of RADIUS users, with should not be split up in more groups!

Instead of getting all the group members to determine if the user is part of that list I would use the memberOf/isMemberOf attribute (assuming that your directory supports this feature). This attribute will tell you if a user belongs to a group without having to retrieve all group members.
This other answer might help.

You need to look at into MaxValRange and learn how to retrieve more values using C#.
We have a very simple sample, but, alas, it is in Java

Related

How does UserPrincipal.FindByIdentity(PrincipalContext context, string identityValue) query Active Directory?

I am using .NET Framework 4.8 by necessity. I am running into an issue where:
UserPrincipal.FindByIdentity(context, username); is resulting in a System.DirectoryServices.AccountManagement.MultipleMatchesException exception for a specific username. I can retrieve other users just fine.
There are two accounts in my Active Directory that this user utilizes, however, both of them have different UPNs, sAMAccountNames, etc.
I took a look at the IdentityType enum and the FindByIdentity overload that allows for an exact IdentityType look-up. With this information, I used each possible IdentityType and tried the searches:
None of these lines of code result in a System.DirectoryServices.AccountManagement.MultipleMatchesException exception. The Sid and Guid look-ups fail because the username field isn't in the right format, and the other look-ups either pull the user or pull null.
So what am I missing here? Does the overload that leaves out a specific IdentityType do a different look-up than anything that's possible by supplying an IdentityType?
Edit #1: As Alex pointed out, I left out that I tried IdentityType.UserPrincipalName from my screenshot. This was just a cropping mistake. That call also does not throw an exception.
When you don't specify which identifier you're using, it's going to try them all at once. The source code is available now. The code that actually builds the query and executes it is here. Specifically it's line 617 where it starts building the filter. The source for IdentityClaimToFilter is here. Then it puts each condition in an OR.
So if we ignore Guid, Sid, and DistinguishedName, since we know those won't match, this is the relevant LDAP query (assuming the username you're using is "UserName"):
(|(sAMAccountName=UserName)(userPrincipalName=UserName)(name=UserName))
Try making that query in PowerShell and see if you get multiple matches (I'm assuming the computer you run this from is joined to the domain you want to search):
$search = [adsisearcher]"(|(sAMAccountName=UserName)(userPrincipalName=UserName)(name=UserName))"
$search.FindAll()
If the sAMAccountName of one account matches the name of another account, for example, you will get multiple matches.

Extract unique listo of fields from maching document

I am new to Lucene, so maybe i have missunderstood something about how it works.
I have indexed few hundred thousand documents with many string field. For example suppose we have 5 string field (named A,B,C,D,E) and the first 3 are indexed (A,B,C) leaving the last two unindexed, only included into the document (i mean D,E). Values in each field may be duplicate, for example assume that the field A is used to store names, and the name 'Richard' appear many times.
When i apply a query i looking for each term in each field, now for example, suppose i get 3K documents that match my query.
Is it possible to get a list of unique values (distinct) of each fields without scan and group the result? I am particularly interested into this because i apply a limit to the documents i actually read, but i would like to get a complete list of unique values in each fields (even the documents i dont' read) of the matching documents.
If this is possibile, can i apply this logic even for unindexed fields (D,E) ?
When doing the search, it will return to you all the documents that have the query conditions. On that result you can do a highlight (which will slow the process), but you can do something like pagination to return the result in pages if you want.
In the highligher you have many methods you can use (depending on what version of Lucene you are using; I am talking here about the last version 4.8.0) like GetBestTextFragments() which takes a parameter called maxNumberFragments. If you set that parameter to 1 then it will return only one value from that particular field even if there might be multiple values that match the query.
I am not sure if that answers your question, but I hope it helps. Regarding the unindexed fields, I dont think you can do that (although I have never tried it).

Does IIS Metabase return sites in Id ascending order?

I'm not sure if my question on the face of it makes full sense, so let me try and elaborate. At the moment I try and check if a website already exists in IIS by creating a new DirectoryEntry:
DirectoryEntry IISWebsites = new DirectoryEntry(MetaBasePath);
MetaBasePath is defined earlier as:
private const string MetaBasePath = "IIS://Localhost/W3SVC";
I check IISWebsites children in a foreach loop and just wondered if this will run through the children in Id order? From what I've read this is actually stored in the DirectoryEntry 'Name' property.
The reason I ask is that if the website name entered by the user in my web setup project isn't found then I want to return the highest id so I can add 1 to it and create a new website with the name supplied by the user.
Having tested this with my IIS it does seem to return it in this order but I need to be sure.
EDIT
I've found the following on Microsoft support (http://support.microsoft.com/kb/240941):
Note that when the metabase is searched for configuration information,
it is enumerated from the bottom, or subkey, to top, or node.
This seems to imply that it does do what I think, but it's not 100% clear if it works on site Id as I'm not sure how this relates to the subkey.
The documentation does not specifically define the order as by site ID so it would not be safe to assume it will always be sorted that way (particularly as your current application eventually gets used with new versions of .NET/Windows/IIS in the future).
Most likely the number of websites is not going to be big enough that enumerating them to find the max would not be a bottleneck.
Even so, you can run a search for websites and specify the order using DirectorySearcher.Sort.
Note that in regards to your edit and how configuration information is enumerated, that does not related to sort order. The one sentence taken out of context is not as clear. Read it in context of the whole paragraph and it is clear that the enumeration behavior is related to metabase property inheritance.

C# get obscure Active Directory Attributes

I'm trying to retrieve some obsure Active Directory Attributes:
msexchmailboxsecuritydescriptor, and
terminalservicesprofilepath (in userparameters)
I am having trouble getting to both of them.
For example, for msexchmailboxsecuritydescriptor, if I have code similar to the following:
DirectoryEntry deresult = result.GetDirectoryEntry();
byte[] bteMailACL =(byte[])deresult.Properties["msexchmailboxsecuritydescriptor"].Value;
It complains that I cannot cast System.__ComObject to System.Byte[], but I have seen several example that use code similar to the above.
How do I understand these blobs of information?
I think your problem is in .Value part of the statement. Not sure how the examples have been doing it but I've noticed that whenever I call an AD Property like that, I always get an array back of which I get index 0 in case of single result items.
just changing the last statment to:
byte[] btwMailACL = (byte[])deresult.Properties["msexchmailboxsecuritydescriptor"][0];
solves your problem.
Edit: for production code, please do remember that this can throw a NullReferenceException so do check if the property actually returned a value before calling on the index.
(Tested on my machine and working as above)

How to find matching URLs except for certain query strings?

I am using the URL for an HTTP resource as unique identifiers for the resources (surprise).
These are all different:
http://localhost/Docs/SomeDocument?group=33&checksafety=true
http://localhost/Docs/SomeDocument?group=11&checksafety=true
http://localhost/Docs/SomeDocument?group=11&checksafety=false
However, I have a third query parameter that should not differentiate resources (on the server side, it pulls the same data from the database).
These are the same (the group and checksafety parameters are the same):
http://localhost/Docs/SomeDocument?group=11&checksafety=false&rendergroup=A
http://localhost/Docs/SomeDocument?group=11&checksafety=false&rendergroup=B
http://localhost/Docs/SomeDocument?rendergroup=C&group=11&checksafety=false
Is a regex appropriate here?
Is there a better way?
I am using C#, .NET 3.5 and ASP.NET.
You could split to get the querystring, then split to get each group, see if all of them have the same number of groups (by group I mean "variable=value"). Analyse each group individually and eliminate the ones that doesn't care.
Then, it is easier to analyse. Here are some ideas
put each group into a List and order it (and then iterate to see if they are the same
put each group into a Set and check if the Union is equal a Set individually.
do this process using the Uri and UriBuilder, and use them for the match verification after removing the "irrelevant" groups
--EDIT included Nick Berardi suggestion

Categories

Resources