You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
6.5 KiB

10 years ago
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package ldap
  5. import (
  6. "crypto/tls"
  7. "errors"
  8. "log"
  9. "net"
  10. "sync"
  11. "github.com/gogits/gogs/modules/asn1-ber"
  12. )
  13. const (
  14. MessageQuit = 0
  15. MessageRequest = 1
  16. MessageResponse = 2
  17. MessageFinish = 3
  18. )
  19. type messagePacket struct {
  20. Op int
  21. MessageID uint64
  22. Packet *ber.Packet
  23. Channel chan *ber.Packet
  24. }
  25. // Conn represents an LDAP Connection
  26. type Conn struct {
  27. conn net.Conn
  28. isTLS bool
  29. isClosing bool
  30. Debug debugging
  31. chanConfirm chan bool
  32. chanResults map[uint64]chan *ber.Packet
  33. chanMessage chan *messagePacket
  34. chanMessageID chan uint64
  35. wgSender sync.WaitGroup
  36. wgClose sync.WaitGroup
  37. once sync.Once
  38. }
  39. // Dial connects to the given address on the given network using net.Dial
  40. // and then returns a new Conn for the connection.
  41. func Dial(network, addr string) (*Conn, error) {
  42. c, err := net.Dial(network, addr)
  43. if err != nil {
  44. return nil, NewError(ErrorNetwork, err)
  45. }
  46. conn := NewConn(c)
  47. conn.start()
  48. return conn, nil
  49. }
  50. // DialTLS connects to the given address on the given network using tls.Dial
  51. // and then returns a new Conn for the connection.
  52. func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
  53. c, err := tls.Dial(network, addr, config)
  54. if err != nil {
  55. return nil, NewError(ErrorNetwork, err)
  56. }
  57. conn := NewConn(c)
  58. conn.isTLS = true
  59. conn.start()
  60. return conn, nil
  61. }
  62. // NewConn returns a new Conn using conn for network I/O.
  63. func NewConn(conn net.Conn) *Conn {
  64. return &Conn{
  65. conn: conn,
  66. chanConfirm: make(chan bool),
  67. chanMessageID: make(chan uint64),
  68. chanMessage: make(chan *messagePacket, 10),
  69. chanResults: map[uint64]chan *ber.Packet{},
  70. }
  71. }
  72. func (l *Conn) start() {
  73. go l.reader()
  74. go l.processMessages()
  75. l.wgClose.Add(1)
  76. }
  77. // Close closes the connection.
  78. func (l *Conn) Close() {
  79. l.once.Do(func() {
  80. l.isClosing = true
  81. l.wgSender.Wait()
  82. l.Debug.Printf("Sending quit message and waiting for confirmation")
  83. l.chanMessage <- &messagePacket{Op: MessageQuit}
  84. <-l.chanConfirm
  85. close(l.chanMessage)
  86. l.Debug.Printf("Closing network connection")
  87. if err := l.conn.Close(); err != nil {
  88. log.Print(err)
  89. }
  90. l.conn = nil
  91. l.wgClose.Done()
  92. })
  93. l.wgClose.Wait()
  94. }
  95. // Returns the next available messageID
  96. func (l *Conn) nextMessageID() uint64 {
  97. if l.chanMessageID != nil {
  98. if messageID, ok := <-l.chanMessageID; ok {
  99. return messageID
  100. }
  101. }
  102. return 0
  103. }
  104. // StartTLS sends the command to start a TLS session and then creates a new TLS Client
  105. func (l *Conn) StartTLS(config *tls.Config) error {
  106. messageID := l.nextMessageID()
  107. if l.isTLS {
  108. return NewError(ErrorNetwork, errors.New("ldap: already encrypted"))
  109. }
  110. packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
  111. packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
  112. request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationExtendedRequest, nil, "Start TLS")
  113. request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, "1.3.6.1.4.1.1466.20037", "TLS Extended Command"))
  114. packet.AppendChild(request)
  115. l.Debug.PrintPacket(packet)
  116. _, err := l.conn.Write(packet.Bytes())
  117. if err != nil {
  118. return NewError(ErrorNetwork, err)
  119. }
  120. packet, err = ber.ReadPacket(l.conn)
  121. if err != nil {
  122. return NewError(ErrorNetwork, err)
  123. }
  124. if l.Debug {
  125. if err := addLDAPDescriptions(packet); err != nil {
  126. return err
  127. }
  128. ber.PrintPacket(packet)
  129. }
  130. if packet.Children[1].Children[0].Value.(uint64) == 0 {
  131. conn := tls.Client(l.conn, config)
  132. l.isTLS = true
  133. l.conn = conn
  134. }
  135. return nil
  136. }
  137. func (l *Conn) sendMessage(packet *ber.Packet) (chan *ber.Packet, error) {
  138. if l.isClosing {
  139. return nil, NewError(ErrorNetwork, errors.New("ldap: connection closed"))
  140. }
  141. out := make(chan *ber.Packet)
  142. message := &messagePacket{
  143. Op: MessageRequest,
  144. MessageID: packet.Children[0].Value.(uint64),
  145. Packet: packet,
  146. Channel: out,
  147. }
  148. l.sendProcessMessage(message)
  149. return out, nil
  150. }
  151. func (l *Conn) finishMessage(messageID uint64) {
  152. if l.isClosing {
  153. return
  154. }
  155. message := &messagePacket{
  156. Op: MessageFinish,
  157. MessageID: messageID,
  158. }
  159. l.sendProcessMessage(message)
  160. }
  161. func (l *Conn) sendProcessMessage(message *messagePacket) bool {
  162. if l.isClosing {
  163. return false
  164. }
  165. l.wgSender.Add(1)
  166. l.chanMessage <- message
  167. l.wgSender.Done()
  168. return true
  169. }
  170. func (l *Conn) processMessages() {
  171. defer func() {
  172. for messageID, channel := range l.chanResults {
  173. l.Debug.Printf("Closing channel for MessageID %d", messageID)
  174. close(channel)
  175. delete(l.chanResults, messageID)
  176. }
  177. close(l.chanMessageID)
  178. l.chanConfirm <- true
  179. close(l.chanConfirm)
  180. }()
  181. var messageID uint64 = 1
  182. for {
  183. select {
  184. case l.chanMessageID <- messageID:
  185. messageID++
  186. case messagePacket, ok := <-l.chanMessage:
  187. if !ok {
  188. l.Debug.Printf("Shutting down - message channel is closed")
  189. return
  190. }
  191. switch messagePacket.Op {
  192. case MessageQuit:
  193. l.Debug.Printf("Shutting down - quit message received")
  194. return
  195. case MessageRequest:
  196. // Add to message list and write to network
  197. l.Debug.Printf("Sending message %d", messagePacket.MessageID)
  198. l.chanResults[messagePacket.MessageID] = messagePacket.Channel
  199. // go routine
  200. buf := messagePacket.Packet.Bytes()
  201. _, err := l.conn.Write(buf)
  202. if err != nil {
  203. l.Debug.Printf("Error Sending Message: %s", err.Error())
  204. break
  205. }
  206. case MessageResponse:
  207. l.Debug.Printf("Receiving message %d", messagePacket.MessageID)
  208. if chanResult, ok := l.chanResults[messagePacket.MessageID]; ok {
  209. chanResult <- messagePacket.Packet
  210. } else {
  211. log.Printf("Received unexpected message %d", messagePacket.MessageID)
  212. ber.PrintPacket(messagePacket.Packet)
  213. }
  214. case MessageFinish:
  215. // Remove from message list
  216. l.Debug.Printf("Finished message %d", messagePacket.MessageID)
  217. close(l.chanResults[messagePacket.MessageID])
  218. delete(l.chanResults, messagePacket.MessageID)
  219. }
  220. }
  221. }
  222. }
  223. func (l *Conn) reader() {
  224. defer func() {
  225. l.Close()
  226. }()
  227. for {
  228. packet, err := ber.ReadPacket(l.conn)
  229. if err != nil {
  230. l.Debug.Printf("reader: %s", err.Error())
  231. return
  232. }
  233. addLDAPDescriptions(packet)
  234. message := &messagePacket{
  235. Op: MessageResponse,
  236. MessageID: packet.Children[0].Value.(uint64),
  237. Packet: packet,
  238. }
  239. if !l.sendProcessMessage(message) {
  240. return
  241. }
  242. }
  243. }