github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/ldap.v2/bind.go (about)

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