aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/emersion/go-imap/client/cmd_noauth.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/emersion/go-imap/client/cmd_noauth.go')
-rw-r--r--vendor/github.com/emersion/go-imap/client/cmd_noauth.go174
1 files changed, 174 insertions, 0 deletions
diff --git a/vendor/github.com/emersion/go-imap/client/cmd_noauth.go b/vendor/github.com/emersion/go-imap/client/cmd_noauth.go
new file mode 100644
index 0000000..f9b34d3
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/client/cmd_noauth.go
@@ -0,0 +1,174 @@
+package client
+
+import (
+ "crypto/tls"
+ "errors"
+ "net"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-imap/commands"
+ "github.com/emersion/go-imap/responses"
+ "github.com/emersion/go-sasl"
+)
+
+var (
+ // ErrAlreadyLoggedIn is returned if Login or Authenticate is called when the
+ // client is already logged in.
+ ErrAlreadyLoggedIn = errors.New("Already logged in")
+ // ErrTLSAlreadyEnabled is returned if StartTLS is called when TLS is already
+ // enabled.
+ ErrTLSAlreadyEnabled = errors.New("TLS is already enabled")
+ // ErrLoginDisabled is returned if Login or Authenticate is called when the
+ // server has disabled authentication. Most of the time, calling enabling TLS
+ // solves the problem.
+ ErrLoginDisabled = errors.New("Login is disabled in current state")
+)
+
+// SupportStartTLS checks if the server supports STARTTLS.
+func (c *Client) SupportStartTLS() (bool, error) {
+ return c.Support("STARTTLS")
+}
+
+// StartTLS starts TLS negotiation.
+func (c *Client) StartTLS(tlsConfig *tls.Config) error {
+ if c.isTLS {
+ return ErrTLSAlreadyEnabled
+ }
+
+ if tlsConfig == nil {
+ tlsConfig = new(tls.Config)
+ }
+ if tlsConfig.ServerName == "" {
+ tlsConfig = tlsConfig.Clone()
+ tlsConfig.ServerName = c.serverName
+ }
+
+ cmd := new(commands.StartTLS)
+
+ err := c.Upgrade(func(conn net.Conn) (net.Conn, error) {
+ // Flag connection as in upgrading
+ c.upgrading = true
+ if status, err := c.execute(cmd, nil); err != nil {
+ return nil, err
+ } else if err := status.Err(); err != nil {
+ return nil, err
+ }
+
+ // Wait for reader to block.
+ c.conn.WaitReady()
+ tlsConn := tls.Client(conn, tlsConfig)
+ if err := tlsConn.Handshake(); err != nil {
+ return nil, err
+ }
+
+ // Capabilities change when TLS is enabled
+ c.locker.Lock()
+ c.caps = nil
+ c.locker.Unlock()
+
+ return tlsConn, nil
+ })
+ if err != nil {
+ return err
+ }
+
+ c.isTLS = true
+ return nil
+}
+
+// SupportAuth checks if the server supports a given authentication mechanism.
+func (c *Client) SupportAuth(mech string) (bool, error) {
+ return c.Support("AUTH=" + mech)
+}
+
+// Authenticate indicates a SASL authentication mechanism to the server. If the
+// server supports the requested authentication mechanism, it performs an
+// authentication protocol exchange to authenticate and identify the client.
+func (c *Client) Authenticate(auth sasl.Client) error {
+ if c.State() != imap.NotAuthenticatedState {
+ return ErrAlreadyLoggedIn
+ }
+
+ mech, ir, err := auth.Start()
+ if err != nil {
+ return err
+ }
+
+ cmd := &commands.Authenticate{
+ Mechanism: mech,
+ }
+
+ irOk, err := c.Support("SASL-IR")
+ if err != nil {
+ return err
+ }
+ if irOk {
+ cmd.InitialResponse = ir
+ }
+
+ res := &responses.Authenticate{
+ Mechanism: auth,
+ InitialResponse: ir,
+ RepliesCh: make(chan []byte, 10),
+ }
+ if irOk {
+ res.InitialResponse = nil
+ }
+
+ status, err := c.execute(cmd, res)
+ if err != nil {
+ return err
+ }
+ if err = status.Err(); err != nil {
+ return err
+ }
+
+ c.locker.Lock()
+ c.state = imap.AuthenticatedState
+ c.caps = nil // Capabilities change when user is logged in
+ c.locker.Unlock()
+
+ if status.Code == "CAPABILITY" {
+ c.gotStatusCaps(status.Arguments)
+ }
+
+ return nil
+}
+
+// Login identifies the client to the server and carries the plaintext password
+// authenticating this user.
+func (c *Client) Login(username, password string) error {
+ if state := c.State(); state == imap.AuthenticatedState || state == imap.SelectedState {
+ return ErrAlreadyLoggedIn
+ }
+
+ c.locker.Lock()
+ loginDisabled := c.caps != nil && c.caps["LOGINDISABLED"]
+ c.locker.Unlock()
+ if loginDisabled {
+ return ErrLoginDisabled
+ }
+
+ cmd := &commands.Login{
+ Username: username,
+ Password: password,
+ }
+
+ status, err := c.execute(cmd, nil)
+ if err != nil {
+ return err
+ }
+ if err = status.Err(); err != nil {
+ return err
+ }
+
+ c.locker.Lock()
+ c.state = imap.AuthenticatedState
+ c.caps = nil // Capabilities change when user is logged in
+ c.locker.Unlock()
+
+ if status.Code == "CAPABILITY" {
+ c.gotStatusCaps(status.Arguments)
+ }
+ return nil
+}