hsoj/ldap — pull request #4 by wizardcypress (2013-08-22 13:19:31+00:00)
Title: NewLDAPTLSConnectioin fail

When using TLS ldap, it seems that the code doesn't work as expected.
In conn.go: startTLS()，before tls.Client start and re-assign new tls connection to l.conn, another goroutine running reader() is already reading(block) on old l.conn which is not tls connection. So after tls handshake finish, the packet reads from l.conn is not through tls. This will cause the packet crash.

So I suggest add a channel to LDAPConnection, when use tls ldap, the reader() will stop reading on old l.conn and wait for tls handshake to finish. After handshake finish, use new l.conn(which is through tls) to read packet.
So that will solve the problem.

```code
diff --git a/conn.go b/conn.go
index 7d38a15..f38a51c 100644
--- a/conn.go
+++ b/conn.go
@@ -47,6 +47,7 @@ type LDAPConnection struct {
closeLock sync.RWMutex
chanMessageID chan uint64
connected bool
+ tlsEstablish chan bool
}

// Connect connects using information in LDAPConnection.
@@ -55,6 +56,7 @@ func (l *LDAPConnection) Connect() error {
l.chanResults = map[uint64]chan *ber.Packet{}
l.chanProcessMessage = make(chan *messagePacket)
l.chanMessageID = make(chan uint64)
+ l.tlsEstablish = make(chan bool)

if l.conn == nil {
var c net.Conn
@@ -87,6 +89,7 @@ func (l *LDAPConnection) Connect() error {
if err != nil {
return err
}
+ l.tlsEstablish <-true
}
return nil
}
@@ -157,6 +160,7 @@ func (l *LDAPConnection) startTLS() error {
}

err = l.sendReqRespPacket(messageID, packet)
+
if err != nil {
return err
}
@@ -313,7 +317,14 @@ func (l *LDAPConnection) finishMessage(MessageID uint64) {

func (l *LDAPConnection) reader() {
defer l.Close()
+ counter := 0
for {
+ counter++
+ // if using tls, the second packet is transfered through tls
+ // Must wait until new tls connection establish
+ if l.IsTLS && counter == 2 {
+ <-l.tlsEstablish
+ }
p, err := ber.ReadPacket(l.conn)
if err != nil {
if l.Debug {
@@ -324,7 +335,7 @@ func (l *LDAPConnection) reader() {

addLDAPDescriptions(p)

- message_id := p.Children[0].Value.(uint64)
+ message_id := p.Children[0].Value.(uint64)
message_packet := &messagePacket{Op: MessageResponse, MessageID: message_id, Packet: p}

l.readerToChanResults(message_packet)

```