external.go raw

   1  package sasl
   2  
   3  import (
   4  	"bytes"
   5  	"errors"
   6  )
   7  
   8  // The EXTERNAL mechanism name.
   9  const External = "EXTERNAL"
  10  
  11  type externalClient struct {
  12  	Identity string
  13  }
  14  
  15  func (a *externalClient) Start() (mech string, ir []byte, err error) {
  16  	mech = External
  17  	ir = []byte(a.Identity)
  18  	return
  19  }
  20  
  21  func (a *externalClient) Next(challenge []byte) (response []byte, err error) {
  22  	return nil, ErrUnexpectedServerChallenge
  23  }
  24  
  25  // An implementation of the EXTERNAL authentication mechanism, as described in
  26  // RFC 4422. Authorization identity may be left blank to indicate that the
  27  // client is requesting to act as the identity associated with the
  28  // authentication credentials.
  29  func NewExternalClient(identity string) Client {
  30  	return &externalClient{identity}
  31  }
  32  
  33  // ExternalAuthenticator authenticates users with the EXTERNAL mechanism. If
  34  // the identity is left blank, it indicates that it is the same as the one used
  35  // in the external credentials. If identity is not empty and the server doesn't
  36  // support it, an error must be returned.
  37  type ExternalAuthenticator func(identity string) error
  38  
  39  type externalServer struct {
  40  	done         bool
  41  	authenticate ExternalAuthenticator
  42  }
  43  
  44  func (a *externalServer) Next(response []byte) (challenge []byte, done bool, err error) {
  45  	if a.done {
  46  		return nil, false, ErrUnexpectedClientResponse
  47  	}
  48  
  49  	// No initial response, send an empty challenge
  50  	if response == nil {
  51  		return []byte{}, false, nil
  52  	}
  53  
  54  	a.done = true
  55  
  56  	if bytes.Contains(response, []byte("\x00")) {
  57  		return nil, false, errors.New("sasl: identity contains a NUL character")
  58  	}
  59  
  60  	return nil, true, a.authenticate(string(response))
  61  }
  62  
  63  // NewExternalServer creates a server implementation of the EXTERNAL
  64  // authentication mechanism, as described in RFC 4422.
  65  func NewExternalServer(authenticator ExternalAuthenticator) Server {
  66  	return &externalServer{authenticate: authenticator}
  67  }
  68