-
Notifications
You must be signed in to change notification settings - Fork 4
/
sasl.go
102 lines (84 loc) · 3.39 KB
/
sasl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright 2013 The Go-IMAP Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the go-imap.LICENSE file.
package imap
import (
"errors"
"fmt"
)
// Note:
// Most of this code was copied, with some modifications, from net/smtp. It
// would be better if Go provided a standard package (e.g. crypto/sasl) that
// could be shared by SMTP, IMAP, and other packages.
// ServerInfo contains information about the IMAP server with which SASL
// authentication is about to be attempted.
type ServerInfo struct {
Name string // Server name
TLS bool // Encryption status
Auth []string // Supported authentication mechanisms
}
// SASL is the interface for performing challenge-response authentication.
type SASL interface {
// Start begins SASL authentication with the server. It returns the
// authentication mechanism name and "initial response" data (if required by
// the selected mechanism). A non-nil error causes the client to abort the
// authentication attempt.
//
// A nil ir value is different from a zero-length value. The nil value
// indicates that the selected mechanism does not use an initial response,
// while a zero-length value indicates an empty initial response, which must
// be sent to the server.
Start(s *ServerInfo) (mech string, ir []byte, err error)
// Next continues challenge-response authentication. A non-nil error causes
// the client to abort the authentication attempt.
Next(challenge []byte) (response []byte, err error)
}
type externalAuth []byte
// ExternalAuth returns an implementation of the EXTERNAL authentication
// mechanism, as described in RFC 4422. Authorization identity may be left blank
// to indicate that the client is requesting to act as the identity associated
// with the authentication credentials.
func ExternalAuth(identity string) SASL {
return externalAuth(identity)
}
func (a externalAuth) Start(s *ServerInfo) (mech string, ir []byte, err error) {
return "EXTERNAL", a, nil
}
func (a externalAuth) Next(challenge []byte) (response []byte, err error) {
return nil, errors.New("unexpected server challenge")
}
type plainAuth []byte
// PlainAuth returns an 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 PlainAuth(username, password, identity string) SASL {
return plainAuth(identity + "\x00" + username + "\x00" + password)
}
func (a plainAuth) Start(s *ServerInfo) (mech string, ir []byte, err error) {
if !s.TLS {
err = NotAvailableError("AUTH=PLAIN")
} else {
mech, ir = "PLAIN", a
}
return
}
func (a plainAuth) Next(challenge []byte) (response []byte, err error) {
return nil, errors.New("unexpected server challenge")
}
type xoauth2Auth []byte
// xoauth2Auth returns an implementation of the XOAUTH2 authentication mechanism, as
// described in https://developers.google.com/gmail/xoauth2_protocol.
func XOAUTH2Auth(username, token string) SASL {
return xoauth2Auth(fmt.Sprintf("user=%s\x01auth=Bearer %s\x01\x01", username, token))
}
func (a xoauth2Auth) Start(s *ServerInfo) (mech string, ir []byte, err error) {
if !s.TLS {
err = NotAvailableError("AUTH=XOAUTH2")
} else {
mech, ir = "XOAUTH2", a
}
return
}
func (a xoauth2Auth) Next(challenge []byte) (response []byte, err error) {
return nil, errors.New("unexpected server challenge")
}