diff --git a/internal/mbxs/connect.go b/internal/mbxs/connect.go index b1d50988..94e5e6ab 100644 --- a/internal/mbxs/connect.go +++ b/internal/mbxs/connect.go @@ -250,10 +250,11 @@ func Connect(server string, port int, netType string, minTLSVer uint16, logger z } // Login uses the provided client connection and credentials to login to the -// remote server. -func Login(client *client.Client, username string, password string, logger zerolog.Logger) error { +// IMAP server using plaintext authentication. Most servers will reject logins +// unless TLS is used. +func Login(c *client.Client, username string, password string, logger zerolog.Logger) error { - if client == nil { + if c == nil { errMsg := fmt.Sprintf( "invalid (nil) client received while attempting login for account %s", username, @@ -264,8 +265,35 @@ func Login(client *client.Client, username string, password string, logger zerol return fmt.Errorf(errMsg) } + // Due to logic applied during connection establishment this is highly + // unlikely to be true, but on the mischance that it is we issue a + // warning. + if !c.IsTLS() { + logger.Warn().Msg("WARNING: Connection to server is insecure (TLS is not enabled)") + } + + // Make sure that LOGINDISABLED capability has not been set. When this is + // advertised by the server the LOGIN command is rejected. A common + // scenario where this capability is set is when the client has not yet + // established a secure TLS connection. + // https://datatracker.ietf.org/doc/html/rfc3501#section-6.2.3 + loginDisabled, capErr := c.Support(IMAPv4CapabilityLoginDisabled) + if capErr != nil { + return fmt.Errorf( + "failed to detect support for logins: %w", + capErr, + ) + } + + if loginDisabled { + return fmt.Errorf( + "server has disabled logins: %w", + client.ErrLoginDisabled, + ) + } + logger.Debug().Msg("Logging in") - if err := client.Login(username, password); err != nil { + if err := c.Login(username, password); err != nil { errMsg := "login error occurred" logger.Error().Err(err).Msg(errMsg) diff --git a/internal/mbxs/constants.go b/internal/mbxs/constants.go index bf070d2e..06eb710f 100644 --- a/internal/mbxs/constants.go +++ b/internal/mbxs/constants.go @@ -29,3 +29,22 @@ const ( // NetTypeTCP6 indicates an IPv6-only network. NetTypeTCP6 string = "tcp6" ) + +// IMAP commands +const ( + + // The LOGIN command identifies the client to the server and carries the + // plaintext password authenticating this user. + // https://datatracker.ietf.org/doc/html/rfc3501#section-6.2.3 + IMAPv4CommandLogin string = "LOGIN" +) + +// IMAP capabilities +const ( + + // The LOGINDISABLED capability indicates that the LOGIN command is not + // permitted. This is most often due to TLS not active for the current + // connection. + // https://datatracker.ietf.org/doc/html/rfc3501#section-6.1.1 + IMAPv4CapabilityLoginDisabled string = "LOGINDISABLED" +)