78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
package sasl
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
)
|
|
|
|
// The PLAIN mechanism name.
|
|
const Plain = "PLAIN"
|
|
|
|
type plainClient struct {
|
|
Identity string
|
|
Username string
|
|
Password string
|
|
}
|
|
|
|
func (a *plainClient) Start() (mech string, ir []byte, err error) {
|
|
mech = "PLAIN"
|
|
ir = []byte(a.Identity + "\x00" + a.Username + "\x00" + a.Password)
|
|
return
|
|
}
|
|
|
|
func (a *plainClient) Next(challenge []byte) (response []byte, err error) {
|
|
return nil, ErrUnexpectedServerChallenge
|
|
}
|
|
|
|
// A client implementation of the PLAIN authentication mechanism, as described
|
|
// in RFC 4616. Authorization identity may be left blank to indicate that it is
|
|
// the same as the username.
|
|
func NewPlainClient(identity, username, password string) Client {
|
|
return &plainClient{identity, username, password}
|
|
}
|
|
|
|
// Authenticates users with an identity, a username and a password. If the
|
|
// identity is left blank, it indicates that it is the same as the username.
|
|
// If identity is not empty and the server doesn't support it, an error must be
|
|
// returned.
|
|
type PlainAuthenticator func(identity, username, password string) error
|
|
|
|
type plainServer struct {
|
|
done bool
|
|
authenticate PlainAuthenticator
|
|
}
|
|
|
|
func (a *plainServer) Next(response []byte) (challenge []byte, done bool, err error) {
|
|
if a.done {
|
|
err = ErrUnexpectedClientResponse
|
|
return
|
|
}
|
|
|
|
// No initial response, send an empty challenge
|
|
if response == nil {
|
|
return []byte{}, false, nil
|
|
}
|
|
|
|
a.done = true
|
|
|
|
parts := bytes.Split(response, []byte("\x00"))
|
|
if len(parts) != 3 {
|
|
err = errors.New("Invalid response")
|
|
return
|
|
}
|
|
|
|
identity := string(parts[0])
|
|
username := string(parts[1])
|
|
password := string(parts[2])
|
|
|
|
err = a.authenticate(identity, username, password)
|
|
done = true
|
|
return
|
|
}
|
|
|
|
// A server implementation of the PLAIN authentication mechanism, as described
|
|
// in RFC 4616.
|
|
func NewPlainServer(authenticator PlainAuthenticator) Server {
|
|
return &plainServer{authenticate: authenticator}
|
|
}
|