wstrange / dartdap

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

Exception when parsing search result #1

Closed NoNotNow closed 9 years ago

NoNotNow commented 9 years ago

I'm using the dartdap library to connect to an LDAP server on Win 2008. The bind operation works fine. As soon as I perform any search I get an exception while the result is parsed by dartdap.

Exception while processing message. Exception RangeError: Value not in range (158) The stack trace points here:

package:dartdap/src/connection/connection_manager.dart:297:21 Here is the code I use:

var filter = Filter.substring("CN=ma*");
var attrs = ["dn", "cn", "objectClass"];
LDAPConfiguration ldapConfig = new LDAPConfiguration("ldap.yaml","default");
LDAPConnection ldap;
ldapConfig.getConnection(false).then((LDAPConnection ldap){
  ldap.bind(/*bindDN*/"CN=CP LDAP,OU=Contract Program,DC=mydomain,DC=de",/*password*/"xxxxx").then((_){
    ldap.search("DC=mydomain,DC=de", filter, attrs).stream.forEach((item)=>print(item)).catchError((err) =>print(err));
  }).catchError((err)=>print(err));    
}).catchError((err)=>print(err));

Here is the log:

INFO: 2015-02-22 19:34:10.843: Connection params dc1.mydomain.de 389 ssl=false
FINEST: 2015-02-22 19:34:10.847: Creating socket to dc1.mydomain.de:389 ssl=false
FINE: 2015-02-22 19:34:10.890: Connected to dc1.mydomain.de:389
FINEST: 2015-02-22 19:34:10.897: Send pending message()
FINE: 2015-02-22 19:34:10.898: Sending message Msg(id=2, op=BND_REQ,controls=null)
FINEST: 2015-02-22 19:34:10.904: LdapMesssage bytes = 30 50 2 1 2 60 4b 2 1 3 4 3b 43 4e 3d 43 50 20 4c 44 41 50 2c 4f 55 3d 43 6f 6e 74 72 61 63 74 20 50 72 6f 67 72 61 6d 2c 44 43 3d 77 61 6c 6c 73 74 72 65 65 74 69 6e 73 74 69 74 75 74 65 2c 44 43 3d 64 65 80 9 48 61 6c 6c 6f 30 38 31 35 
FINEST: 2015-02-22 19:34:10.944: ENTER ******* _handleData  bytes=22 data=[48, 132, 0, 0, 0, 16, 2, 1, 2, 97, 132, 0, 0, 0, 7, 10, 1, 0, 4, 0, 4, 0]
FINE: 2015-02-22 19:34:10.950: Got LDAP Message. Id = 2 protocolOp = Seq[ASN1Object(tag=a) OctetString() OctetString() ]
FINE: 2015-02-22 19:34:10.950: Received LDAP message Msg(id=2, op=BND_RESP,controls=null) byte length=22
FINEST: 2015-02-22 19:34:10.951: handle response tag=BND_RESP
FINEST: 2015-02-22 19:34:10.952: +++++ new response op = Msg(id=2, op=BND_RESP,controls=null)
FINEST: 2015-02-22 19:34:10.952: parse ldap result == Seq[ASN1Object(tag=a) OctetString() OctetString() ]
FINEST: 2015-02-22 19:34:10.953: Create Controls from null
FINE: 2015-02-22 19:34:10.954: Request Msg(id=2, op=BND_REQ,controls=null) serviced in 56 ms
FINEST: 2015-02-22 19:34:10.954: Send pending message()
FINEST: 2015-02-22 19:34:10.958: Send pending message()
FINE: 2015-02-22 19:34:10.958: Sending message Msg(id=3, op=SRCH_REQ,controls=null)
FINEST: 2015-02-22 19:34:10.958: LdapMesssage bytes = 30 57 2 1 3 63 52 4 1c 44 43 3d 77 61 6c 6c 73 74 72 65 65 74 69 6e 73 74 69 74 75 74 65 2c 44 43 3d 64 65 2 1 2 2 1 0 2 2 3 e8 2 2 27 10 1 1 0 a4 a 4 2 43 4e 30 4 80 2 6d 61 30 15 4 2 64 6e 4 2 63 6e 4 b 6f 62 6a 65 63 74 43 6c 61 73 73 
FINEST: 2015-02-22 19:34:10.993: ENTER ******* _handleData  bytes=132 data=[48, 132, 0, 0, 0, 126, 2, 1, 0, 120, 132, 0, 0, 0, 93, 10, 1, 2, 4, 0, 4, 86, 48, 48, 48, 48, 48, 48, 53, 55, 58, 32, 76, 100, 97, 112, 69, 114, 114, 58, 32, 68, 83, 73, 68, 45, 48, 67, 48, 67, 48, 57, 69, 69, 44, 32, 99, 111, 109, 109, 101, 110, 116, 58, 32, 69, 114, 114, 111, 114, 32, 100, 101, 99, 111, 100, 105, 110, 103, 32, 108, 100, 97, 112, 32, 109, 101, 115, 115, 97, 103, 101, 44, 32, 100, 97, 116, 97, 32, 48, 44, 32, 118, 49, 100, 98, 49, 0, 138, 22, 49, 46, 51, 46, 54, 46, 49, 46, 52, 46, 49, 46, 49, 52, 54, 54, 46, 50, 48, 48, 51, 54]
FINEST: 2015-02-22 19:34:10.995: Controls = ASN1Object(tag=8a) [138, 22, 49, 46, 51, 46, 54, 46, 49, 46, 52, 46, 49, 46, 49, 52, 54, 54, 46, 50, 48, 48, 51, 54]
SEVERE: 2015-02-22 19:34:10.998: Exception while processing message. Exception RangeError: Value not in range (158)
Unhandled exception:
Uncaught Error: type 'StackTrace' is not a subtype of type 'String' of 'message'.
Stack Trace:
#0      Logger.severe (package:logging/logging.dart:225:22)
#1      _handleData (package:dartdap/src/connection/connection_manager.dart:297:21)
#2      _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#3      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#4      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#5      _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:590)
#6      _StreamController._add (dart:async/stream_controller.dart:465)
#7      _StreamController.add (dart:async/stream_controller.dart:412)
#8      _onData (dart:io-patch/socket_patch.dart:1730)
#9      _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#10     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#11     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#12     _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:590)
#13     _StreamController._add (dart:async/stream_controller.dart:465)
#14     _StreamController.add (dart:async/stream_controller.dart:412)
#15     _RawSocket._RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1300)
#16     _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:695)
#17     _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#18     _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#19     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:84)
#20     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:131)

#0      _rootHandleUncaughtError.<anonymous closure> (dart:async/zone.dart:886)
#1      _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#2      _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#3      _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:84)
#4      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:131)
wstrange commented 9 years ago

Thanks for the bug report!

I will need your help tracking this down, as I do not have a Windows 2008 AD server.

Can you use the latest source from github. You will need SDK 1.9 as I have started to convert this to async/await.

I have a hunch that the problem is in parsing the controls. LDAP controls are still a mystery to me- so I suspect the ASN parser is blowing up on controls that AD is returning.

Can you try to set a debug breakpoint in ldap_message.dart - in the method LDAPMessage.fromBytes(Uint8List bytes) (try around line 91).

If you don't care about controls - a temporary workaround (and perhaps a way to validate the problem is with the controls) is to just comment out that block (90->101).

wstrange commented 9 years ago

I just made a minor commit that should give you a better stacktrace printout.

NoNotNow commented 9 years ago

I'm traveling ATM. I'll get back to you with the stacktrace tonight.

NoNotNow commented 9 years ago

Thanks for looking into this!

So I set a break point where you recommended. This line throws the error:

var c2 = new ASN1Sequence.fromBytes(c);

at this moment c = [16, 22, 49, 46, 51, 46, 54, 46, 49, 46, 52, 46, 49, 46, 49, 52, 54, 54, 46, 50, 48, 48, 51, 54]

stepping inside:

class ASN1Sequence extends ASN1Object { 
  List<ASN1Object> elements = new List();
  /**
   * Create a sequence fromt the byte array [b]
   * Note that bytes array b could be longer than the actual encoded sequence - in which case
   * we ignore any remaining bytes
   */
  ASN1Sequence.fromBytes(Uint8List b) {
    this.tag = b[0];
    // todo; Check if b[0] is a valid sequence type???
    if( (tag & 0x30) == 0 )
      throw new ASN1Exception("The tag ${tag} does not look like a sequence type");

    _encodedBytes = b;
    super._initFromBytes();
    //print("ASN1Sequence valbytes=${hex(valueBytes())}");
    _decodeSeq(); <---- t h i s   t h r o w s   t h e   e x c e p t i o n
  }
[...]

Commenting out the code you recommended I still get the same exception.

wstrange commented 9 years ago

Hi Manuel,

Hmmmm, OK this looks rather involved.

The control code parsing is blowing up - which as I mentioned before is a rather tricky and I am not that familiar with it.

A couple of quick hacks that you can try:

See if that passes the parser.

The other option is to comment out the control parsing code altogether:

 ///  var c2 = new ASN1Sequence.fromBytes(c);

 ///  _controls = c2;

You will get basic features - but at this point it should not matter the library does not look at server controls right now.

I am severely time challenged right now, and as I mentioned I do not have a Win 2008 system - so if yo want to debug this you will need to dive in to ASN.1 parsing. The byte stream will have to be decoded (easier to do if you print it in hex vs. ascii), and you will have to look at the values being passed back to understand why the parser does not think it is a valid ASN sequence.

Hopefully you can work around this by commenting out that section for now.

On Mon Feb 23 2015 at 4:14:34 PM Manuel Riviere notifications@github.com wrote:

Thanks for looking into this!

So I set a break point where you recommended. This line throws the error:

var c2 = new ASN1Sequence.fromBytes(c);

at this moment c = [16, 22, 49, 46, 51, 46, 54, 46, 49, 46, 52, 46, 49, 46, 49, 52, 54, 54, 46, 50, 48, 48, 51, 54]

stepping inside:

class ASN1Sequence extends ASN1Object { List elements = new List(); /**

  • Create a sequence fromt the byte array [b]
  • Note that bytes array b could be longer than the actual encoded sequence - in which case
  • we ignore any remaining bytes */ ASN1Sequence.fromBytes(Uint8List b) { this.tag = b[0]; // todo; Check if b[0] is a valid sequence type??? if( (tag & 0x30) == 0 ) throw new ASN1Exception("The tag ${tag} does not look like a sequence type");

    _encodedBytes = b; super._initFromBytes(); //print("ASN1Sequence valbytes=${hex(valueBytes())}"); _decodeSeq(); <---- t h i s t h r o w s t h e e x c e p t i o n } [...]

Commenting out the code you recommended I still get the same exception.

— Reply to this email directly or view it on GitHub https://github.com/wstrange/dartdap/issues/1#issuecomment-75659046.

wstrange commented 9 years ago

OK - so I looked at this in more depth tonight...

Good news and bad news....

The dartdap control parsing code is going to need a lot more work. LDAP encodes controls using "Context specific" BER encoding - which means you have to look at the tag and based on the value apply a context specific decoding.

In this case, the tag value 0x8a is an Extended Response Protocol Operation - and the encoded value is assumed to be an ASN1 Octect string with the OID of the response.

Decoding your example as an Octect String yields an OID of: 1.3.6.1.4.1.1466.20036

Which if you look at the LDAP spec at https://tools.ietf.org/html/rfc2251 means that the server is disconnecting because it does not like the LDAP request.

So the good news: If you look at the AD server logs it should tell you why it does not like the request.

The bad news: dartdap may not be not sending AD a proper search request. It also needs to implement control parsing correctly...

One possible problem: AD may not like the fact that you are doing a search over 389 (non SSL). The result code should indicate if this is the case. You might try SSL and see if that fixes the problem.

wstrange commented 9 years ago

I committed a bandaid fix tonight which should at least parse the control correctly.

We still need to find out why AD is rejecting the search

chrisridd commented 9 years ago

The main problem here in the current code is that it is decoding the ExtendedResponse in the wrong place. It is another kind of ResponseOp not a Control, so you need to decode it like you do bind responses etc. i.e. it should automatically end up in the _protocolOp variable. IOW delete lines 101-106 of ldap_message.dart. Your description of LDAPMessage at the top of this file could do with ExtendedRequest/ExtendedResponse and Controls being added.

If you want to test how you deal with a notice of disconnection (the extended response Manuel's seeing) configure a server like OpenDJ to idle out client connections reasonably quickly, connect to the server, and wait for the idle limit.

wstrange commented 9 years ago

Thanks Chris - I came to the same conclusion late last night ....

Let me see if I can refactor this in the next few days. Stay tuned Manuel...

wstrange commented 9 years ago

Manuel,

This is partially fixed (pull the latest commit from github).

The code should recognize the ExtendedResponse code that AD is returning. It is not going to gracefully handle it (should result in an LDAPException). I still need to figure that out...

You will need to find the underlying cause for AD wanting to shut down the connection. I suspect AD wants to see the connection made over SSL.

NoNotNow commented 9 years ago

Thanks Warren & Chris. I appreciate your effort. Much of this is out of my league. I ran the code with the latest update on port 636. Let me know if there is anything else I can do.

INFO: 2015-02-24 21:44:27.384: Connection params dc1.mydomain.de 636 ssl=true
FINEST: 2015-02-24 21:44:27.384: Creating socket to dc1.mydomain.de:636 ssl=true
FINE: 2015-02-24 21:44:27.415: MongoReplyMessage(ResponseTo:8, cursorId: 0, numberReturned:1, responseFlags:8, {connectionId: 1, updatedExisting: false, upserted: I£o@ñ®Å½`ÿ;ƾÕâù, n: 1, syncMillis: 0, writtenTo: null, err: null, ok: 1.0})
FINE: 2015-02-24 21:44:27.415: MongoReplyMessage(ResponseTo:8, cursorId: 0, numberReturned:1, responseFlags:8, {connectionId: 1, updatedExisting: false, upserted: I£o@ñ®Å½`ÿ;ƾÕâù, n: 1, syncMillis: 0, writtenTo: null, err: null, ok: 1.0})
FINE: 2015-02-24 21:44:27.415: Completing MongoReplyMessage(ResponseTo:8, cursorId: 0, numberReturned:1, responseFlags:8, {connectionId: 1, updatedExisting: false, upserted: I£o@ñ®Å½`ÿ;ƾÕâù, n: 1, syncMillis: 0, writtenTo: null, err: null, ok: 1.0})
WARNING: 2015-02-24 21:44:27.883: Invalid Certificate issuer= CN=mydomain-DC1-CA,DC=mydomain,DC=de subject=CN=DC1.mydomain.de
WARNING: 2015-02-24 21:44:27.883: SSL Connection will proceed. Please fix the certificate
FINE: 2015-02-24 21:44:27.914: Connected to dc1.mydomain.de:636
FINEST: 2015-02-24 21:44:27.930: Send pending message()
FINE: 2015-02-24 21:44:27.930: Sending message Msg(id=2, op=BND_REQ,controls=null)
FINEST: 2015-02-24 21:44:27.977: ENTER ******* _handleData  bytes=22 data=[48, 132, 0, 0, 0, 16, 2, 1, 2, 97, 132, 0, 0, 0, 7, 10, 1, 0, 4, 0, 4, 0]
FINE: 2015-02-24 21:44:27.977: Got LDAP Message. Id = 2 protocolOp = Seq[ASN1Object(tag=a) OctetString() OctetString() ]
FINE: 2015-02-24 21:44:27.977: Received LDAP message Msg(id=2, op=BND_RESP,controls=null) byte length=22
FINEST: 2015-02-24 21:44:27.977: handle response tag=BND_RESP
FINEST: 2015-02-24 21:44:27.977: +++++ new response op = Msg(id=2, op=BND_RESP,controls=null)
FINEST: 2015-02-24 21:44:27.977: parse ldap result == Seq[ASN1Object(tag=a) OctetString() OctetString() ]
FINE: 2015-02-24 21:44:27.992: Request Msg(id=2, op=BND_REQ,controls=null) serviced in 62 ms
FINEST: 2015-02-24 21:44:27.992: Send pending message()
FINEST: 2015-02-24 21:44:27.992: Send pending message()
FINE: 2015-02-24 21:44:27.992: Sending message Msg(id=3, op=SRCH_REQ,controls=null)
FINEST: 2015-02-24 21:44:28.039: ENTER ******* _handleData  bytes=132 data=[48, 132, 0, 0, 0, 126, 2, 1, 0, 120, 132, 0, 0, 0, 93, 10, 1, 2, 4, 0, 4, 86, 48, 48, 48, 48, 48, 48, 53, 55, 58, 32, 76, 100, 97, 112, 69, 114, 114, 58, 32, 68, 83, 73, 68, 45, 48, 67, 48, 67, 48, 57, 69, 69, 44, 32, 99, 111, 109, 109, 101, 110, 116, 58, 32, 69, 114, 114, 111, 114, 32, 100, 101, 99, 111, 100, 105, 110, 103, 32, 108, 100, 97, 112, 32, 109, 101, 115, 115, 97, 103, 101, 44, 32, 100, 97, 116, 97, 32, 48, 44, 32, 118, 49, 100, 98, 49, 0, 138, 22, 49, 46, 51, 46, 54, 46, 49, 46, 52, 46, 49, 46, 49, 52, 54, 54, 46, 50, 48, 48, 51, 54]
FINE: 2015-02-24 21:44:28.039: Got LDAP Message. Id = 0 protocolOp = Seq[ASN1Object(tag=a) OctetString() OctetString(00000057: LdapErr: DSID-0C0C09EE, comment: Error decoding ldap message, data 0, v1db1
SEVERE: 2015-02-24 21:44:28.039: Exception while processing message. Exception LDAPException(Server sent us an unknown message id = 0 opCode=120, result=null)
SEVERE: 2015-02-24 21:44:28.039: #0      ConnectionManager._handleMessage (package:dartdap/src/connection/connection_manager.dart:344:7)
#1      _handleData (package:dartdap/src/connection/connection_manager.dart:299:33)
#2      _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#3      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#4      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#5      _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#6      _StreamController._add (dart:async/stream_controller.dart:470)
#7      _StreamController.add (dart:async/stream_controller.dart:417)
#8      _onData (dart:io-patch/socket_patch.dart:1764)
#9      _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#10     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#11     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#12     _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#13     _StreamController._add (dart:async/stream_controller.dart:470)
#14     _StreamController.add (dart:async/stream_controller.dart:417)
#15     _sendReadEvent (dart:io/secure_socket.dart:1137)
#16     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:16)
#17     _Timer._handleTimeout (dart:isolate-patch/timer_impl.dart:392)
#18     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:145)
wstrange commented 9 years ago

Hi Manuel - I think we are slowly making progress...

AD is sending "LdapErr: DSID-0C0C09EE, comment: Error decoding ldap message" - so it does not like the message.

Chris pointed out that I was incorrectly encoding the search filter. I just pushed a fix - can you pull it down and try once more.

NoNotNow commented 9 years ago

Hi Warren, I just ran search with your latest fix and am still seeing: Error decoding ldap message, data 0, v1db1.

FINE: 2015-02-25 07:27:45.571: Completing MongoReplyMessage(ResponseTo:9, cursorId: 0, numberReturned:1, responseFlags:8, {connectionId: 4, updatedExisting: false, upserted: ¢°_䭁aV™âH(úÁ%, n: 1, syncMillis: 0, writtenTo: null, err: null, ok: 1.0})
INFO: 2015-02-25 07:27:45.578: Connection params dc1.mydomain.de 636 ssl=true
FINEST: 2015-02-25 07:27:45.578: Creating socket to dc1.mydomain.de:636 ssl=true
WARNING: 2015-02-25 07:27:46.426: Invalid Certificate issuer= CN=mydomain-DC1-CA,DC=mydomain,DC=de subject=CN=DC1.mydomain.de
WARNING: 2015-02-25 07:27:46.426: SSL Connection will proceed. Please fix the certificate
FINE: 2015-02-25 07:27:46.473: Connected to dc1.mydomain.de:636
FINEST: 2015-02-25 07:27:46.488: Send pending message()
FINE: 2015-02-25 07:27:46.488: Sending message Msg(id=2, op=BND_REQ,controls=null)
FINEST: 2015-02-25 07:27:46.551: ENTER ******* _handleData  bytes=22 data=[48, 132, 0, 0, 0, 16, 2, 1, 2, 97, 132, 0, 0, 0, 7, 10, 1, 0, 4, 0, 4, 0]
FINE: 2015-02-25 07:27:46.551: Got LDAP Message. Id = 2 protocolOp = Seq[ASN1Object(tag=a) OctetString() OctetString() ]
FINE: 2015-02-25 07:27:46.551: Received LDAP message Msg(id=2, op=BND_RESP,controls=null) byte length=22
FINEST: 2015-02-25 07:27:46.551: handle response tag=BND_RESP
FINEST: 2015-02-25 07:27:46.551: +++++ new response op = Msg(id=2, op=BND_RESP,controls=null)
FINEST: 2015-02-25 07:27:46.551: parse ldap result == Seq[ASN1Object(tag=a) OctetString() OctetString() ]
FINE: 2015-02-25 07:27:46.566: Request Msg(id=2, op=BND_REQ,controls=null) serviced in 77 ms
FINEST: 2015-02-25 07:27:46.566: Send pending message()
FINEST: 2015-02-25 07:27:46.566: Send pending message()
FINE: 2015-02-25 07:27:46.566: Sending message Msg(id=3, op=SRCH_REQ,controls=null)
FINEST: 2015-02-25 07:27:46.630: ENTER ******* _handleData  bytes=132 data=[48, 132, 0, 0, 0, 126, 2, 1, 0, 120, 132, 0, 0, 0, 93, 10, 1, 2, 4, 0, 4, 86, 48, 48, 48, 48, 48, 48, 53, 55, 58, 32, 76, 100, 97, 112, 69, 114, 114, 58, 32, 68, 83, 73, 68, 45, 48, 67, 48, 67, 48, 57, 69, 69, 44, 32, 99, 111, 109, 109, 101, 110, 116, 58, 32, 69, 114, 114, 111, 114, 32, 100, 101, 99, 111, 100, 105, 110, 103, 32, 108, 100, 97, 112, 32, 109, 101, 115, 115, 97, 103, 101, 44, 32, 100, 97, 116, 97, 32, 48, 44, 32, 118, 49, 100, 98, 49, 0, 138, 22, 49, 46, 51, 46, 54, 46, 49, 46, 52, 46, 49, 46, 49, 52, 54, 54, 46, 50, 48, 48, 51, 54]
FINE: 2015-02-25 07:27:46.630: Got LDAP Message. Id = 0 protocolOp = Seq[ASN1Object(tag=a) OctetString() OctetString(00000057: LdapErr: DSID-0C0C09EE, comment: Error decoding ldap message, data 0, v1db1
FINE: 2015-02-25 07:27:46.630: Received LDAP message Msg(id=0, op=78,controls=null) byte length=132
FINEST: 2015-02-25 07:27:46.630: handle response tag=78
FINEST: 2015-02-25 07:27:46.630: +++++ new response op = Msg(id=0, op=78,controls=null)
FINEST: 2015-02-25 07:27:46.630: parse ldap result == Seq[ASN1Object(tag=a) OctetString() OctetString(00000057: LdapErr: DSID-0C0C09EE, comment: Error decoding ldap message, data 0, v1db1
#1      _handleData (package:dartdap/src/connection/connection_manager.dart:299:33)
#2      _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#3      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#4      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#5      _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#6      _StreamController._add (dart:async/stream_controller.dart:470)
#7      _StreamController.add (dart:async/stream_controller.dart:417)
#8      _onData (dart:io-patch/socket_patch.dart:1764)
#9      _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#10     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#11     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#12     _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#13     _StreamController._add (dart:async/stream_controller.dart:470)
#14     _StreamController.add (dart:async/stream_controller.dart:417)
#15     _sendReadEvent (dart:io/secure_socket.dart:1137)
#16     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:16)
#17     _Timer._handleTimeout (dart:isolate-patch/timer_impl.dart:392)
#18     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:145)
NoNotNow commented 9 years ago

I ran the dartdap search code on an Ubuntu server. The error causes a crash even when I run in production mode. How can I catch this error properly?

var filter = Filter.substring("CN=ma*");
var attrs = ["dn", "cn", "objectClass"];
LDAPConfiguration ldapConfig = new LDAPConfiguration("ldap.yaml","default");
LDAPConnection ldap;
ldapConfig.getConnection(false).then((LDAPConnection ldap){
  ldap.bind(/*bindDN*/"CN=CP LDAP,OU=Contract Program,DC=mydomain,DC=de",/*password*/"xxxxx").then((_){
    ldap.search("DC=mydomain,DC=de", filter, attrs).stream.forEach((item)=>print(item)).catchError((err) =>print(err));
  }).catchError((err)=>print(err));    
}).catchError((err)=>print(err));

The output I get is different in that the LDAP server resets the connection right after the search.

INFO: 2015-02-26 17:58:12.287: Connection params dc1.mydomain.de 636 ssl=true
FINEST: 2015-02-26 17:58:12.293: Creating socket to dc1.mydomain.de:636 ssl=true
WARNING: 2015-02-26 17:58:17.339: Invalid Certificate issuer= CN=mydomain-DC1-CA,DC=mydomain,DC=de subject=CN=DC1.mydomain.de
WARNING: 2015-02-26 17:58:17.340: SSL Connection will proceed. Please fix the certificate
FINE: 2015-02-26 17:58:17.346: Connected to dc1.mydomain.de:636
FINEST: 2015-02-26 17:58:17.355: Send pending message()
FINE: 2015-02-26 17:58:17.357: Sending message Msg(id=2, op=BND_REQ,controls=null)
FINEST: 2015-02-26 17:58:17.369: ENTER ******* _handleData  bytes=22 data=[48, 132, 0, 0, 0, 16, 2, 1, 2, 97, 132, 0, 0, 0, 7, 10, 1, 0, 4, 0, 4, 0]
FINE: 2015-02-26 17:58:17.380: Got LDAP Message. Id = 2 protocolOp = Seq[ASN1Object(tag=a) OctetString() OctetString() ]
FINE: 2015-02-26 17:58:17.380: Received LDAP message Msg(id=2, op=BND_RESP,controls=null) byte length=22
FINEST: 2015-02-26 17:58:17.382: handle response tag=BND_RESP
FINEST: 2015-02-26 17:58:17.383: +++++ new response op = Msg(id=2, op=BND_RESP,controls=null)
FINEST: 2015-02-26 17:58:17.384: parse ldap result == Seq[ASN1Object(tag=a) OctetString() OctetString() ]
FINE: 2015-02-26 17:58:17.386: Request Msg(id=2, op=BND_REQ,controls=null) serviced in 31 ms
FINEST: 2015-02-26 17:58:17.386: Send pending message()
FINEST: 2015-02-26 17:58:17.393: Send pending message()
FINE: 2015-02-26 17:58:17.393: Sending message Msg(id=3, op=SRCH_REQ,controls=null)
SEVERE: 2015-02-26 17:58:17.403: Socket error = SocketException: OS Error: Connection reset by peer, errno = 104, address = dc1.mydomain.de, port = 46708
Unhandled exception:
Uncaught Error: LDAPException(Socket error = SocketException: OS Error: Connection reset by peer, errno = 104, address = dc1.mydomain.de, port = 46708, result=null)
Stack Trace:
#0      ConnectionManager.connect.<connect_async_body>.<anonymous closure> (package:dartdap/src/connection/connection_manager.dart:163:11)
#1      _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#2      _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:360)
#3      _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:374)
#4      _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:279)
#5      _StreamController&&_SyncStreamControllerDispatch._sendError (dart:async/stream_controller.dart:599)
#6      _StreamController._addError (dart:async/stream_controller.dart:478)
#7      _StreamController.addError (dart:async/stream_controller.dart:431)
#8      _onError (dart:io-patch/socket_patch.dart:1787)
#9      _RootZone.runBinaryGuarded (dart:async/zone.dart:1104)
#10     _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:358)
#11     _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:371)
#12     _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:279)
#13     _StreamController&&_SyncStreamControllerDispatch._sendError (dart:async/stream_controller.dart:599)
#14     _StreamController._addError (dart:async/stream_controller.dart:478)
#15     _StreamController.addError (dart:async/stream_controller.dart:431)
#16     _reportError (dart:io/secure_socket.dart:936)
#17     _RootZone.runBinaryGuarded (dart:async/zone.dart:1104)
#18     _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:358)
#19     _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:374)
#20     _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:279)
#21     _StreamController&&_SyncStreamControllerDispatch._sendError (dart:async/stream_controller.dart:599)
#22     _StreamController._addError (dart:async/stream_controller.dart:478)
#23     _StreamController.addError (dart:async/stream_controller.dart:431)
#24     _RawSocket._RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1344)
#25     _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#26     _RootZone.bindUnaryCallback.<anonymous closure> (dart:async/zone.dart:1122)
#27     _NativeSocket.reportError (dart:io-patch/socket_patch.dart:944)
#28     multiplex (dart:io-patch/socket_patch.dart:786)
#29     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:142)

#0      _rootHandleUncaughtError.<anonymous closure> (dart:async/zone.dart:886)
#1      _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#2      _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#3      _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:96)
#4      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:143)
wstrange commented 9 years ago

Hi Manuel

I assume you are running the code on Ubuntu, but still querying AD. I believe this the same underlying issue: AD does not like the search that dartdap is sending, and is closing the socket connection. The socket error handling should be more graceful - but the issue is the same.

I am going to have to find an AD server to test against - since I am not sure what is going on.

Chris is going to contribute some filter unit tests -which should help to debug the issue. Unfortunately this is not a work project for me - so my time is going to be very limited. I will keep this issue open until it is fixed.

wstrange commented 9 years ago

OK - I think this one is solved...

A couple of search params were being encoded as ASN1 integers when they should have been enums.

I am now getting expected results on my test AD instance

Manuel - Can you refresh from git and see if this fixes your issue?

chrisridd commented 9 years ago

Well spotted - the bug was in asn1lib!

NoNotNow commented 9 years ago

Well done, I'm getting search results. Depending on the search, I'm getting a range error though.

SEVERE: 2015-03-01 00:04:05.923: Socket error = RangeError: Value not in range: 8246  stacktrace=#0      _rangeCheck (dart:typed_data-patch/typed_data.dart:3612)
#1      _Uint8ArrayView._Uint8ArrayView (dart:typed_data-patch/typed_data.dart:2634)
#2      _ByteBuffer.asUint8List (dart:typed_data-patch/typed_data.dart:751)
#3      Uint8List.Uint8List.view (dart:typed_data:487)
#4      ASN1Object.valueBytes (package:asn1lib/asn1object.dart:144:16)
#5      ASN1Sequence._decodeSeq (package:asn1lib/asn1sequence.dart:69:45)
#6      ASN1Sequence.ASN1Sequence.fromBytes (package:asn1lib/asn1sequence.dart:26:15)
#7      LDAPMessage.LDAPMessage.fromBytes (package:dartdap/src/protocol/ldap_message.dart:83:16)
#8      createTransformer.<anonymous closure> (package:dartdap/src/connection/ldap_transformer.dart:13:24)
#9      _HandlerEventSink.add (dart:async/stream_transformers.dart:216)
#10     _handleData (dart:async/stream_transformers.dart:119)
#11     _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#12     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#13     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#14     _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#15     _StreamController._add (dart:async/stream_controller.dart:470)
#16     _StreamController.add (dart:async/stream_controller.dart:417)
#17     _onData (dart:io-patch/socket_patch.dart:1764)
#18     _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#20     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#21     _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#22     _StreamController._add (dart:async/stream_controller.dart:470)
#23     _StreamController.add (dart:async/stream_controller.dart:417)
#24     _sendReadEvent (dart:io/secure_socket.dart:1137)
#25     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:16)
#26     _Timer._handleTimeout (dart:isolate-patch/timer_impl.dart:392)
#27     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:145)

Unhandled exception:
Uncaught Error: LDAPException(Socket error = RangeError: Value not in range: 8246 stacktrace=#0      _rangeCheck (dart:typed_data-patch/typed_data.dart:3612)
#1      _Uint8ArrayView._Uint8ArrayView (dart:typed_data-patch/typed_data.dart:2634)
#2      _ByteBuffer.asUint8List (dart:typed_data-patch/typed_data.dart:751)
#3      Uint8List.Uint8List.view (dart:typed_data:487)
#4      ASN1Object.valueBytes (package:asn1lib/asn1object.dart:144:16)
#5      ASN1Sequence._decodeSeq (package:asn1lib/asn1sequence.dart:69:45)
#6      ASN1Sequence.ASN1Sequence.fromBytes (package:asn1lib/asn1sequence.dart:26:15)
#7      LDAPMessage.LDAPMessage.fromBytes (package:dartdap/src/protocol/ldap_message.dart:83:16)
#8      createTransformer.<anonymous closure> (package:dartdap/src/connection/ldap_transformer.dart:13:24)
#9      _HandlerEventSink.add (dart:async/stream_transformers.dart:216)
#10     _handleData (dart:async/stream_transformers.dart:119)
#11     _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#12     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#13     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#14     _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#15     _StreamController._add (dart:async/stream_controller.dart:470)
#16     _StreamController.add (dart:async/stream_controller.dart:417)
#17     _onData (dart:io-patch/socket_patch.dart:1764)
#18     _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#20     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#21     _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#22     _StreamController._add (dart:async/stream_controller.dart:470)
#23     _StreamController.add (dart:async/stream_controller.dart:417)
#24     _sendReadEvent (dart:io/secure_socket.dart:1137)
#25     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:16)
#26     _Timer._handleTimeout (dart:isolate-patch/timer_impl.dart:392)
#27     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:145)
, result=null)
Stack Trace:
#0      ConnectionManager.connect.<connect_async_body>.<anonymous closure> (package:dartdap/src/connection/connection_manager.dart:161:10)
#1      _RootZone.runBinaryGuarded (dart:async/zone.dart:1104)
#2      _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:358)
#3      _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:374)
#4      _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:279)
#5      _SinkTransformerStreamSubscription._addError (dart:async/stream_transformers.dart:81)
#6      _handleData (dart:async/stream_transformers.dart:121)
#7      _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#8      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#9      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#10     _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#11     _StreamController._add (dart:async/stream_controller.dart:470)
#12     _StreamController.add (dart:async/stream_controller.dart:417)
#13     _onData (dart:io-patch/socket_patch.dart:1764)
#14     _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#15     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#16     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#17     _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#18     _StreamController._add (dart:async/stream_controller.dart:470)
#19     _StreamController.add (dart:async/stream_controller.dart:417)
#20     _sendReadEvent (dart:io/secure_socket.dart:1137)
#21     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:16)
#22     _Timer._handleTimeout (dart:isolate-patch/timer_impl.dart:392)
#23     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:145)

#0      _rootHandleUncaughtError.<anonymous closure> (dart:async/zone.dart:886)
#1      _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#2      _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#3      _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:96)
#4      _Timer._handleTimeout (dart:isolate-patch/timer_impl.dart:399)
#5      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:145)
wstrange commented 9 years ago

Can you try limiting the number of results returned to see if that makes a difference. I may not be correctly handling a search that exceeds the limit.

I added a named parameter:

ldap.search("CN=Users,DC=openrock,DC=org", f2, ["dn"],sizeLimit:100)

Let me know if that makes a difference

NoNotNow commented 9 years ago

I can limit the size of results that are received. The exception now says "Not done": If it helps, I could set a breakpoint somewhere (please specify) and send you step by step details.

Also, is there a way to catch these kinds of exceptions? I assume the .chatchError doesn't do because of the async nature of the application. I don't want the whole application to crash every time the LDAP sends something unexpected.

Unhandled exception:
Uncaught Error: Not done
Stack Trace:
#0      ResponseHandler.handleResponse (package:dartdap/src/protocol/response_handler.dart:37:9)
#1      ConnectionManager._handleLDAPMessage (package:dartdap/src/connection/connection_manager.dart:274:45)
#2      ConnectionManager.connect.<connect_async_body>.<anonymous closure> (package:dartdap/src/connection/connection_manager.dart:158:77)
#3      _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#4      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#5      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#6      _SinkTransformerStreamSubscription._add (dart:async/stream_transformers.dart:67)
#7      _EventSinkWrapper.add (dart:async/stream_transformers.dart:14)
#8      createTransformer.<anonymous closure> (package:dartdap/src/connection/ldap_transformer.dart:15:20)
#9      _HandlerEventSink.add (dart:async/stream_transformers.dart:216)
#10     _handleData (dart:async/stream_transformers.dart:119)
#11     _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#12     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#13     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#14     _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#15     _StreamController._add (dart:async/stream_controller.dart:470)
#16     _StreamController.add (dart:async/stream_controller.dart:417)
#17     _onData (dart:io-patch/socket_patch.dart:1764)
#18     _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
#19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#20     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#21     _StreamController&&_SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:595)
#22     _StreamController._add (dart:async/stream_controller.dart:470)
#23     _StreamController.add (dart:async/stream_controller.dart:417)
#24     _sendReadEvent (dart:io/secure_socket.dart:1137)
#25     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:16)
#26     _Timer._handleTimeout (dart:isolate-patch/timer_impl.dart:392)
#27     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:145)

#0      _rootHandleUncaughtError.<anonymous closure> (dart:async/zone.dart:886)
#1      _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#2      _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#3      _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:96)
#4      _Timer._handleTimeout (dart:isolate-patch/timer_impl.dart:399)
#5      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:145)
chrisridd commented 9 years ago

At "finest" log level the code should log something like "handle response tag" - can you attach that logging?

NoNotNow commented 9 years ago
FINE: 2015-03-01 11:25:13.451: Connected to dc1.mydomain.de:636
FINE: 2015-03-01 11:25:13.467: Sending message Msg(id=2, op=BND_REQ,controls=null)
FINE: 2015-03-01 11:25:13.529: Got LDAP Message. Id = 2 protocolOp = Seq[ASNInteger(0) OctetString() OctetString() ]
FINE: 2015-03-01 11:25:13.529: Received LDAP message Msg(id=2, op=BND_RESP,controls=null)
FINEST: 2015-03-01 11:25:13.529: handle response tag=BND_RESP
FINEST: 2015-03-01 11:25:13.529: +++++ new response op = Msg(id=2, op=BND_RESP,controls=null)
FINEST: 2015-03-01 11:25:13.529: parse ldap result == Seq[ASNInteger(0) OctetString() OctetString() ]
FINE: 2015-03-01 11:25:13.529: Request Msg(id=2, op=BND_REQ,controls=null) serviced in 62 ms
FINE: 2015-03-01 11:25:13.529: Sending message Msg(id=3, op=SRCH_REQ,controls=null)
FINE: 2015-03-01 11:25:13.561: Got LDAP Message. Id = 3 protocolOp = Seq[OctetString(ldaps://ForestDnsZones.mydomain.de/DC=ForestDnsZones,DC=mydomain,DC=de) ]
FINE: 2015-03-01 11:25:13.561: Received LDAP message Msg(id=3, op=SRCH_RES_REF,controls=null)
FINEST: 2015-03-01 11:25:13.561: handle response tag=SRCH_RES_REF
FINE: 2015-03-01 11:25:13.576: Got LDAP Message. Id = 3 protocolOp = Seq[OctetString(ldaps://DomainDnsZones.mydomain.de/DC=DomainDnsZones,DC=mydomain,DC=de) ]
FINE: 2015-03-01 11:25:13.576: Received LDAP message Msg(id=3, op=SRCH_RES_REF,controls=null)
FINEST: 2015-03-01 11:25:13.576: handle response tag=SRCH_RES_REF
FINE: 2015-03-01 11:25:13.576: Got LDAP Message. Id = 3 protocolOp = Seq[OctetString(ldaps://mydomain.de/CN=Configuration,DC=mydomain,DC=de) ]
FINE: 2015-03-01 11:25:13.576: Received LDAP message Msg(id=3, op=SRCH_RES_REF,controls=null)
FINEST: 2015-03-01 11:25:13.576: handle response tag=SRCH_RES_REF
FINE: 2015-03-01 11:25:13.576: Got LDAP Message. Id = 3 protocolOp = Seq[ASNInteger(0) OctetString() OctetString() ]
FINE: 2015-03-01 11:25:13.576: Received LDAP message Msg(id=3, op=SRCH_RES_DONE,controls=null)
FINEST: 2015-03-01 11:25:13.576: handle response tag=SRCH_RES_DONE
FINEST: 2015-03-01 11:25:13.576: +++++ new response op = Msg(id=3, op=SRCH_RES_DONE,controls=null)
FINEST: 2015-03-01 11:25:13.576: parse ldap result == Seq[ASNInteger(0) OctetString() OctetString() ]
FINE: 2015-03-01 11:25:13.576: Request Msg(id=3, op=SRCH_REQ,controls=null) serviced in 46 ms
chrisridd commented 9 years ago

Ah, so your search is returning 3 SearchResultReferences (basically URLs that refer to other servers), which are not being handled by the response_handler handleResponse() method - there's not even a class at the moment to represent this response.

It is not ideal, but if you repeat the search from the information can see AD sending back to you, you should have more success:

  1. ldaps://ForestDnsZones.mydomain.de/DC=ForestDnsZones,DC=mydomain,DC=de
  2. ldaps://DomainDnsZones.mydomain.de/DC=DomainDnsZones,DC=mydomain,DC=de
  3. ldaps://mydomain.de/CN=Configuration,DC=mydomain,DC=de
NoNotNow commented 9 years ago

Hi Chris,

Actually, all I want to do is to authenticate my users, hence they put in their "User logon name" and password and I want to be able to check if the username & password match and get some details about the "Member of" entries, so I can manage their rights.

I'm starting to think that the way I'm approaching this is all wrong.

  1. Do a search for the username
  2. Get the fully qualified DN
  3. Get the LDAP to compare the password of the user with what is stored in AD.

I don't understand why I'm getting these references to other servers. The information I need is on that same server.

Maybe I have to change the filter

var filter = Filter.substring("EmailAddress=*$username");
wstrange commented 9 years ago

Hi Manuel

As Chris mentions, the dartdap library does not handle referrals right now.

Perhaps try your idea of searching for the user first (search on samAccountName) and finding their DN.

To authenticate the user you should collect their credentials and do a bind as the user. The library defaults to using the admin connection, but you can override that. Something like

ldap.bind(userDN, userPassword).

Where userdn is what you discovered from the search operation.

The library should definitely handle exceptions in a more graceful way. I think the way to do this is with "zones" (which limit the exceptions to a zone). I need to do more research on the proper way to do this. I am not sure if it is the responsibility of the dartdap library, or the calling library to wrap it in a zone.

NoNotNow commented 9 years ago

Hi Warren,

Thanks for the hints. I changed my filter to

var filter = Filter.equals("samAccountName","$username");

This gets me one important step closer. The correct DN from the search results gets printed in the log, but doesn't come out of the stream.

ldap.search("DC=wallstreetinstitute,DC=de", filter, attrs,sizeLimit:10).stream.forEach((item)=>print("Search result from stream: $item")).catchError((err) =>print(err));

The referrals still get printed to the log and in the at the end I get the 'not done' exception.

FINEST: 2015-03-02 17:00:01.975: +++++ new response op = Msg(id=3, op=SRCH_RES_DONE,controls=null)
FINEST: 2015-03-02 17:00:01.975: parse ldap result == Seq[ASNInteger(0) OctetString() OctetString() ]
FINE: 2015-03-02 17:00:01.975: Request Msg(id=3, op=SRCH_REQ,controls=null) serviced in 62 ms
Unhandled exception:
Uncaught Error: Not done
Stack Trace:
#0      ResponseHandler.handleResponse (package:dartdap/src/protocol/response_handler.dart:37:9)
#1      ConnectionManager._handleLDAPMessage (package:dartdap/src/connection/connection_manager.dart:274:45)
#2      ConnectionManager.connect.<connect_async_body>.<anonymous closure> (package:dartdap/src/connection/connection_manager.dart:158:77)
#3      _RootZone.runUnaryGuarded (dart:async/zone.dart:1093)
[...]
NoNotNow commented 9 years ago

Interesting, when I wrap the whole thing in zones, I do get a proper result from the stream. https://www.dartlang.org/articles/zones/

NoNotNow commented 9 years ago

This is not the prettiest piece of code that I've ever written, but it works. I'm able to verify users' logins/passwords. I still get the exception, but with runZoned() it doesn't crash my application any more.

Future checkLoginWithLdap(String username, String password) {
  Completer completer= new Completer();
  var filter = Filter.equals("samAccountName", username);
  Map result ={};
  var attrs = ["dn","memberOf"];
  runZoned(() {
    LDAPConfiguration ldapConfig = new LDAPConfiguration("ldapssl.yaml", "default"); 
    LDAPConnection ldap;
    ldapConfig.getConnection(false).then((LDAPConnection ldap) {
      ldap.bind().then((_) {
        ldap.search("DC=mydomain,DC=de", filter, attrs, sizeLimit: 1).stream.forEach((SearchEntry searchEntry) {
          String dn = searchEntry.dn;
          var memberOf = searchEntry.attributes;
          print("memberOf: $memberOf");
          print("dn: $dn");
          //perform bind using search result
          ldap.bind(dn, password).then((LDAPResult ldapResult) { //bind for authentication
            if(ldapResult.resultCode==0){
              print("login successful");
              result['success']=true;
              completer.complete(result);
            }
          }).catchError((error){
            print("username or password wrong");
            result['success']=false;
            completer.complete(result);
          });
        });
      }).catchError((err) => print(err));
    }).catchError((e) => print(e));
  }, onError: (error, stackTrace) {
    print("Error:\n$error \nStacktrace: \n$stackTrace");
  });
  return completer.future;
}
wstrange commented 9 years ago

I am going to close this issue for now