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.

143 lines
4.4 KiB

  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. "errors"
  7. "gopkg.in/asn1-ber.v1"
  8. )
  9. // SimpleBindRequest represents a username/password bind operation
  10. type SimpleBindRequest struct {
  11. // Username is the name of the Directory object that the client wishes to bind as
  12. Username string
  13. // Password is the credentials to bind with
  14. Password string
  15. // Controls are optional controls to send with the bind request
  16. Controls []Control
  17. }
  18. // SimpleBindResult contains the response from the server
  19. type SimpleBindResult struct {
  20. Controls []Control
  21. }
  22. // NewSimpleBindRequest returns a bind request
  23. func NewSimpleBindRequest(username string, password string, controls []Control) *SimpleBindRequest {
  24. return &SimpleBindRequest{
  25. Username: username,
  26. Password: password,
  27. Controls: controls,
  28. }
  29. }
  30. func (bindRequest *SimpleBindRequest) encode() *ber.Packet {
  31. request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
  32. request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
  33. request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, bindRequest.Username, "User Name"))
  34. request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, bindRequest.Password, "Password"))
  35. request.AppendChild(encodeControls(bindRequest.Controls))
  36. return request
  37. }
  38. // SimpleBind performs the simple bind operation defined in the given request
  39. func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) {
  40. packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
  41. packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
  42. encodedBindRequest := simpleBindRequest.encode()
  43. packet.AppendChild(encodedBindRequest)
  44. if l.Debug {
  45. ber.PrintPacket(packet)
  46. }
  47. msgCtx, err := l.sendMessage(packet)
  48. if err != nil {
  49. return nil, err
  50. }
  51. defer l.finishMessage(msgCtx)
  52. packetResponse, ok := <-msgCtx.responses
  53. if !ok {
  54. return nil, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
  55. }
  56. packet, err = packetResponse.ReadPacket()
  57. l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
  58. if err != nil {
  59. return nil, err
  60. }
  61. if l.Debug {
  62. if err := addLDAPDescriptions(packet); err != nil {
  63. return nil, err
  64. }
  65. ber.PrintPacket(packet)
  66. }
  67. result := &SimpleBindResult{
  68. Controls: make([]Control, 0),
  69. }
  70. if len(packet.Children) == 3 {
  71. for _, child := range packet.Children[2].Children {
  72. result.Controls = append(result.Controls, DecodeControl(child))
  73. }
  74. }
  75. resultCode, resultDescription := getLDAPResultCode(packet)
  76. if resultCode != 0 {
  77. return result, NewError(resultCode, errors.New(resultDescription))
  78. }
  79. return result, nil
  80. }
  81. // Bind performs a bind with the given username and password
  82. func (l *Conn) Bind(username, password string) error {
  83. packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
  84. packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
  85. bindRequest := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
  86. bindRequest.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
  87. bindRequest.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, username, "User Name"))
  88. bindRequest.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, password, "Password"))
  89. packet.AppendChild(bindRequest)
  90. if l.Debug {
  91. ber.PrintPacket(packet)
  92. }
  93. msgCtx, err := l.sendMessage(packet)
  94. if err != nil {
  95. return err
  96. }
  97. defer l.finishMessage(msgCtx)
  98. packetResponse, ok := <-msgCtx.responses
  99. if !ok {
  100. return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
  101. }
  102. packet, err = packetResponse.ReadPacket()
  103. l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
  104. if err != nil {
  105. return err
  106. }
  107. if l.Debug {
  108. if err := addLDAPDescriptions(packet); err != nil {
  109. return err
  110. }
  111. ber.PrintPacket(packet)
  112. }
  113. resultCode, resultDescription := getLDAPResultCode(packet)
  114. if resultCode != 0 {
  115. return NewError(resultCode, errors.New(resultDescription))
  116. }
  117. return nil
  118. }