wstrange / dartdap

DART LDAP Client
BSD 2-Clause "Simplified" License
20 stars 14 forks source link

"Not done" exception while handling SEARCH_RESULT_REFERENCE #19

Closed mlesin closed 2 years ago

mlesin commented 6 years ago

In a lightly modified example from dartdap, I'm experiencing "Not done" exception while fetching contents from my AD (Win2008):

Here is the last part of log just before exception thrown:

FINE: 2018-11-10 21:28:29.332397: LDAP message received: Id=3 protocolOp=Seq[OctetString(ldap://ForestDnsZones.mydomain.com/DC=ForestDnsZones,DC=mydomain,DC=com) ]
FINER: 2018-11-10 21:28:29.332403: LDAP response received: SRCH_RES_REF

Looks like SEARCH_RESULT_REFERENCE is not handled properly in ResponseHandler.handleResponse()

wstrange commented 6 years ago

Yea - that code indicates a search referral - which the dartdap client does not implement.

The referral is indicating the search should be re-issued with the new DN. This would be a fairly major change to the client- which I won't get to for a while. You can probably work around this by issuing the search with that DN above.

Here is a description of the referral: https://ldap.com/ldap-result-code-reference-core-ldapv3-result-codes/#rc-referral

EDIT: This is better https://ldapwiki.com/wiki/SearchResultReference

wstrange commented 6 years ago

A good discussion of referral handling: https://sourceforge.net/p/ldap-sdk/discussion/1001257/thread/4208464d/

wstrange commented 6 years ago

I just pushed version 0.3.3 to pub, which has experimental support for returning the referral. I don't have an AD server to test against - so I'm really not sure this works.

There is a new property: List<String> SearchResultEntry.referrals. If you do a search, and this array is not empty, you should repeat the search again using the URI in that array (there will probably only be one). dartdap does not follow referrals automatically - that would be a nice enhancement

I'll leave this bug open to track that feature.

mlesin commented 6 years ago

I've checked it with AD (2008), it works as you described, returning lists with a single URI value inside for 3 elements in my AD:

["ldap://ForestDnsZones.mydomain.com/DC=ForestDnsZones,DC=mydomain,DC=com"]
["ldap://DomainDnsZones.mydomain.com/DC=DomainDnsZones,DC=mydomain,DC=com"]
["ldap://mydomain.com/CN=Configuration,DC=mydomain,DC=com"]

For me, this behaviour is more clean, thank you for a quick fix!

butlermatt commented 5 years ago

@mlesin I just started running into this same behaviour. Do you have a rough example with the search result on how you iterate though the referrals?

mlesin commented 5 years ago

@butlermatt in last version it works out of the box for me, with code provided in example. I didn't dive in inside referrals (don't need for my task), just read their values.

wstrange commented 5 years ago

The current release (0.3.3) has very experimental support for this. It won't follow the referrals (that would be a nice enhancement), but it should return the list of DNs in SearchEntry.referalls.

You need to reissue the search again using those DNs as the new BaseDN. I think you can use any of the DNs returned in the list.

butlermatt commented 5 years ago

@wstrange Yeah based on mlesin's output, it seems to return the full URI including DN's, and it doesn't look like they're parsed from URL to DNs so looks like I may need to try and split the host and DN information. Unfortunately in a difficult situation to debug this as it's a client who accesses it via vpn and remote desktop to the installed dart that is running the ldap clients that connect to other ldap servers. Trial and error debugging is difficult and was hoping a solution had been at least started on his end. I'll need to parse as much as I can from the information I have and try to go from there. Thanks folks

butlermatt commented 5 years ago

Just FYI for anyone who comes across this searching. I was able to make use of the referral links successfully by doing something along of the following:

if (result.referrals.isNotEmpty) {
  var refUri = Uri.parse(result.referrals.first);
  var newBase = refUri.path.substring(1); // Trim off the leading '/'
  await ldapConn.setAuthentication(newBase, password); // Don't use the results of the authentication directly
  return myMethod(...);
}

Basically I trim the dn from the returned referral LDAP URI, using URI parsing as a quick and dirty way to avoid making sure I trimmed off the protocol, host and port info. Then apply setAuthenticate to a new DN, since I can't directly update it in LdapConnection object itself. Then I re-execute the same method with the ldap connection authenticated against the new DN. Obviously sample excludes the various error checking already in place.

For my situation, I'm using Dart 1.x so needed to backport the changes to this and to the asn1lib. While I know Google/Dart's official view is that 2.x is the way, for the foreseeable future we are sticking with the 1.x line until we have the resources in place to move a lot of legacy code and implement some kind of snapshot handling or other packaging mechanism in place for distributing code among various Dart VM levels (RIP dart2dart)

wstrange commented 5 years ago

Thanks Matt - this is super helpful.

Most LDAP SDKs can be configured to follow referrals - so we should probably do the same.

I'm really slammed right now - so I won't be getting to this anytime soon, but if someone out there wants to submit a PR , that would be awesome ;-)