From 5e5e4f3918d8bed055ce026ac64f2688b9236abc Mon Sep 17 00:00:00 2001 From: James Thomas Date: Mon, 14 Jan 2019 12:35:23 -0800 Subject: [PATCH] Add Support for SMTP LOGIN Authentication Method (#1988) This PR adds support for the SMTP LOGIN authentication method. Office 365 Exchange removed support for PLAIN authentication some time ago, and only supports LOGIN and an OAuth2 authentication method. This patch has been tested with a licensed O365 account. This method should also be usable with any other email server that advertises LOGIN in its 250-AUTH response. Note: If using this with O365, the account used must not have MFA enabled. Closes #1663 --- .../admin/AppConfigForm/AppConfigForm.jsx | 1 + server/kolide/app.go | 4 +++ server/mail/mail.go | 32 +++++++++++++++++++ server/service/service_appconfig.go | 2 ++ 4 files changed, 39 insertions(+) diff --git a/frontend/components/forms/admin/AppConfigForm/AppConfigForm.jsx b/frontend/components/forms/admin/AppConfigForm/AppConfigForm.jsx index 82ee968e8c..4776fbd108 100644 --- a/frontend/components/forms/admin/AppConfigForm/AppConfigForm.jsx +++ b/frontend/components/forms/admin/AppConfigForm/AppConfigForm.jsx @@ -15,6 +15,7 @@ import validate from 'components/forms/admin/AppConfigForm/validate'; const authMethodOptions = [ { label: 'Plain', value: 'authmethod_plain' }, { label: 'Cram MD5', value: 'authmethod_cram_md5' }, + { label: 'Login', value: 'authmethod_login' }, ]; const authTypeOptions = [ { label: 'Username and Password', value: 'authtype_username_password' }, diff --git a/server/kolide/app.go b/server/kolide/app.go index bb4e9c0ddc..2ccd7e5717 100644 --- a/server/kolide/app.go +++ b/server/kolide/app.go @@ -30,6 +30,7 @@ type AppConfigService interface { // SMTPAuthMethod const ( AuthMethodNameCramMD5 = "authmethod_cram_md5" + AuthMethodNameLogin = "authmethod_login" AuthMethodNamePlain = "authmethod_plain" AuthTypeNameUserNamePassword = "authtype_username_password" AuthTypeNameNone = "authtype_none" @@ -58,6 +59,7 @@ type SMTPAuthMethod int const ( AuthMethodPlain SMTPAuthMethod = iota AuthMethodCramMD5 + AuthMethodLogin ) func (m SMTPAuthMethod) String() string { @@ -66,6 +68,8 @@ func (m SMTPAuthMethod) String() string { return AuthMethodNamePlain case AuthMethodCramMD5: return AuthMethodNameCramMD5 + case AuthMethodLogin: + return AuthMethodNameLogin default: return "" } diff --git a/server/mail/mail.go b/server/mail/mail.go index 345b51ab83..e9aa926c57 100644 --- a/server/mail/mail.go +++ b/server/mail/mail.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "net/smtp" + "strings" "time" "github.com/kolide/fleet/server/kolide" @@ -70,6 +71,35 @@ func (m mailService) SendEmail(e kolide.Email) error { return m.sendMail(e, msg) } +type loginauth struct { + username string + password string +} + +func LoginAuth(username, password string) smtp.Auth { + return &loginauth{username: username, password: password} +} + +func (l *loginauth) Start(serverInfo *smtp.ServerInfo) (proto string, toServer []byte, err error) { + return "LOGIN", nil, nil +} + +func (l *loginauth) Next(fromServer []byte, more bool) (toServer []byte, err error) { + if !more { + return nil, nil + } + + prompt := strings.TrimSpace(string(fromServer)) + switch prompt { + case "Username:": + return []byte(l.username), nil + case "Password:": + return []byte(l.password), nil + default: + return nil, errors.New("unexpected LOGIN prompt from server") + } +} + func smtpAuth(e kolide.Email) (smtp.Auth, error) { if e.Config.SMTPAuthenticationType != kolide.AuthTypeUserNamePassword { return nil, nil @@ -80,6 +110,8 @@ func smtpAuth(e kolide.Email) (smtp.Auth, error) { auth = smtp.CRAMMD5Auth(e.Config.SMTPUserName, e.Config.SMTPPassword) case kolide.AuthMethodPlain: auth = smtp.PlainAuth("", e.Config.SMTPUserName, e.Config.SMTPPassword, e.Config.SMTPServer) + case kolide.AuthMethodLogin: + auth = LoginAuth(e.Config.SMTPUserName, e.Config.SMTPPassword) default: return nil, fmt.Errorf("unknown SMTP auth type '%d'", e.Config.SMTPAuthenticationMethod) } diff --git a/server/service/service_appconfig.go b/server/service/service_appconfig.go index f922861915..f2d2ec8e6e 100644 --- a/server/service/service_appconfig.go +++ b/server/service/service_appconfig.go @@ -150,6 +150,8 @@ func appConfigFromAppConfigPayload(p kolide.AppConfigPayload, config kolide.AppC config.SMTPAuthenticationMethod = kolide.AuthMethodCramMD5 case kolide.AuthMethodNamePlain: config.SMTPAuthenticationMethod = kolide.AuthMethodPlain + case kolide.AuthMethodNameLogin: + config.SMTPAuthenticationMethod = kolide.AuthMethodLogin default: panic("unknown SMTP AuthMethod: " + *p.SMTPAuthenticationMethod) }