source: code/trunk/vendor/github.com/emersion/go-sasl/login.go@ 822

Last change on this file since 822 was 822, checked in by yakumo.izuru, 22 months ago

Prefer immortal.run over runit and rc.d, use vendored modules
for convenience.

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 2.2 KB
Line 
1package sasl
2
3import (
4 "bytes"
5)
6
7// The LOGIN mechanism name.
8const Login = "LOGIN"
9
10var expectedChallenge = []byte("Password:")
11
12type loginClient struct {
13 Username string
14 Password string
15}
16
17func (a *loginClient) Start() (mech string, ir []byte, err error) {
18 mech = "LOGIN"
19 ir = []byte(a.Username)
20 return
21}
22
23func (a *loginClient) Next(challenge []byte) (response []byte, err error) {
24 if bytes.Compare(challenge, expectedChallenge) != 0 {
25 return nil, ErrUnexpectedServerChallenge
26 } else {
27 return []byte(a.Password), nil
28 }
29}
30
31// A client implementation of the LOGIN authentication mechanism for SMTP,
32// as described in http://www.iana.org/go/draft-murchison-sasl-login
33//
34// It is considered obsolete, and should not be used when other mechanisms are
35// available. For plaintext password authentication use PLAIN mechanism.
36func NewLoginClient(username, password string) Client {
37 return &loginClient{username, password}
38}
39
40// Authenticates users with an username and a password.
41type LoginAuthenticator func(username, password string) error
42
43type loginState int
44
45const (
46 loginNotStarted loginState = iota
47 loginWaitingUsername
48 loginWaitingPassword
49)
50
51type loginServer struct {
52 state loginState
53 username, password string
54 authenticate LoginAuthenticator
55}
56
57// A server implementation of the LOGIN authentication mechanism, as described
58// in https://tools.ietf.org/html/draft-murchison-sasl-login-00.
59//
60// LOGIN is obsolete and should only be enabled for legacy clients that cannot
61// be updated to use PLAIN.
62func NewLoginServer(authenticator LoginAuthenticator) Server {
63 return &loginServer{authenticate: authenticator}
64}
65
66func (a *loginServer) Next(response []byte) (challenge []byte, done bool, err error) {
67 switch a.state {
68 case loginNotStarted:
69 // Check for initial response field, as per RFC4422 section 3
70 if response == nil {
71 challenge = []byte("Username:")
72 break
73 }
74 a.state++
75 fallthrough
76 case loginWaitingUsername:
77 a.username = string(response)
78 challenge = []byte("Password:")
79 case loginWaitingPassword:
80 a.password = string(response)
81 err = a.authenticate(a.username, a.password)
82 done = true
83 default:
84 err = ErrUnexpectedClientResponse
85 }
86
87 a.state++
88 return
89}
Note: See TracBrowser for help on using the repository browser.