mjl- / mox

modern full-featured open source secure mail server for low-maintenance self-hosted email
https://www.xmox.nl
MIT License
3.57k stars 99 forks source link

Empty response to AUTH LOGIN when should return base64 encoded "Username:" #223

Closed gdunstone closed 1 week ago

gdunstone commented 1 week ago

Should EHLO 250-AUTH response have PLAIN and LOGIN first?

I was having trouble getting Authelia to use mox as its submissions server for a notification service. I kept getting this error when trying to use mox: error="failed to dial connection: SMTP AUTH failed: unsupported SMTP AUTH types: ", however it worked when I used gmail.

I had a look at the responses of both gmail and mox and it seems that gmail returns LOGIN and PLAIN before the others:

Response from gmail:

220 smtp.gmail.com ESMTP 41be03b00d2f7-7e6db292aafsm8896834a12.14 - gsmtp
EHLO localhost
250-smtp.gmail.com at your service, [103.216.191.236]
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8

Response from mox v0.0.11

220 my.domain.com ESMTP mox v0.0.11
EHLO localhost
250-my.domain.com
250-PIPELINING
250-SIZE 104857600
250-REQUIRETLS
250-AUTH SCRAM-SHA-256-PLUS SCRAM-SHA-256 SCRAM-SHA-1-PLUS SCRAM-SHA-1 CRAM-MD5 PLAIN LOGIN
250-FUTURERELEASE 5184000 2024-11-30T23:25:13Z
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-LIMITS RCPTMAX=1000
250 SMTPUTF8

After building a dev mox, and placing PLAIN and LOGIN before the others, Authelia worked.

This line: https://github.com/mjl-/mox/blob/b0c4b090102cfdcb3a2ef112fc3f4487ec21ea40/smtpserver/server.go#L906

diff --git a/smtpserver/server.go b/smtpserver/server.go
index 38fa205..575edc8 100644
--- a/smtpserver/server.go
+++ b/smtpserver/server.go
@@ -899,7 +899,7 @@ func (c *conn) cmdHello(p *parser, ehlo bool) {
                        // authentication. The client should select the bare variant when TLS isn't
                        // present, and also not indicate the server supports the PLUS variant in that
                        // case, or it would trigger the mechanism downgrade detection.
-                       c.bwritelinef("250-AUTH SCRAM-SHA-256-PLUS SCRAM-SHA-256 SCRAM-SHA-1-PLUS SCRAM-SHA-1 CRAM-MD5 PLAIN LOGIN")
+                       c.bwritelinef("250-AUTH PLAIN LOGIN SCRAM-SHA-256-PLUS SCRAM-SHA-256 SCRAM-SHA-1-PLUS SCRAM-SHA-1 CRAM-MD5")
                } else {
                        c.bwritelinef("250-AUTH ")
                }

This reponse from mox resulted in successful login by Authelia:

220 my.domain.com ESMTP mox (devel)
EHLO localhost
250-my.domain.com
250-PIPELINING
250-SIZE 104857600
250-REQUIRETLS
250-AUTH PLAIN LOGIN SCRAM-SHA-256-PLUS SCRAM-SHA-256 SCRAM-SHA-1-PLUS SCRAM-SHA-1 CRAM-MD5
250-FUTURERELEASE 5184000 2024-12-01T00:47:52Z
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-LIMITS RCPTMAX=1000
250 SMTPUTF8

I'm not sure if I should raise this with mox or Authelia, and I dont know the spec of how these auth options should be ordered, so if this is fully within spec I can raise this with Authelia instead.

wneessen commented 1 week ago

go-mail dev here. I know that Authelia uses go-mail under the hood and I recognize that error message from our auth modules. Turns out this issue is actually related to go-mail.

It has nothing to do with the order of the supported methods, this is just a coincident. It has to do with the LOGIN auth mechanism specificly and how we handle it. The PLAIN auth should work fine and you should be able to verify that in your installation - I believe Authelia has a config option for that.

The issue is, that in go-mail we expect the server to respond with a base64 encoded representation of either "Username:", "username:" or "User name\x00". I believe there is no formal IETF RFC for "AUTH LOGIN", but there is draft. Mox does not reply with the base64 encoded representation of "Username:" but just responds with an empty 334. Since go-mail expects a different response, it will reject the authentication try with the error message you are seeing.

I suggest that Mox follows the common approach of sending the "Username:". Unless of course @mjl- has a valid point to not do so- in that case I'd be happy to adept mox's behaviour in go-mail.

For refernece, I've checked some mail server implementations/popular mail services and it looks like the common agreement is to send the 334 with the "Username:" in the response:

Postfix:

250-AUTH=LOGIN PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
AUTH LOGIN
334 VXNlcm5hbWU6

Dovecot:

250-AUTH LOGIN PLAIN SCRAM-SHA-1 SCRAM-SHA-256
250-ENHANCEDSTATUSCODES
250-SIZE
250 PIPELINING
AUTH LOGIN
334 VXNlcm5hbWU6

Google:

250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8
AUTH LOGIN
334 VXNlcm5hbWU6

Zoho mail:

250-AUTH LOGIN PLAIN
250 SIZE 53477376
AUTH LOGIN
334 VXNlcm5hbWU6

Yahoo mail:

250 AUTH PLAIN LOGIN XOAUTH2 OAUTHBEARER
AUTH LOGIN
334 VXNlcm5hbWU6

iCloud mail:

250-AUTH LOGIN PLAIN ATOKEN ATOKEN2 WSTOKEN WETOKEN XOAUTH2
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-SMTPUTF8
250 CHUNKING
AUTH LOGIN
334 VXNlcm5hbWU6
wneessen commented 1 week ago

Additional note: While writing a test to adept this behaviour in go-mail, I just noticed that mox, on the second response, answers with "Password". Commonly servers respond with "Password:", "password:" or "Password\x00". Maybe also something to consider here.

Side note: in the next release go-mail will support SCRAM-SHA, so this will become a no-brainer for Authela ;)

wneessen commented 1 week ago

Last side note (I promise): After reading the draft again (especially https://datatracker.ietf.org/doc/html/draft-murchison-sasl-login-00#section-2.1 and https://datatracker.ietf.org/doc/html/draft-murchison-sasl-login-00#section-2.2) I see that it's vage as usual... The clients "SHOULD" ignore any server response (which go-mail does not do) but then again the server "MAY" send responses following one widely deployed client which requires that the challenge strings transmitted by the server be "Username:" and "Password:" respectively

I'll file an issue for go-mail to address the "SHOULD" part in #2.1 but still it might be advisable to follow the common behaviour for mox to follow.

gdunstone commented 1 week ago

Ill update the title of this issue to be clearer

wneessen commented 1 week ago

Created: https://github.com/wneessen/go-mail/issues/311

gdunstone commented 1 week ago

This was resolved in aead73883601ecb259e7a27d834bcbaf8e4af07a

https://github.com/mjl-/mox/commit/aead73883601ecb259e7a27d834bcbaf8e4af07a#diff-0d8b40a06936984b2af0c9839ccdc0e3f3c7e0ce0896b6bb85b2cea56de879a5R1026

mjl- commented 1 week ago

Thanks for the report & analysis! I changed mox to write the "Username:" and "Password:" challenges. Closer to what others services are doing, the internet-draft is just a draft (and it says essentially anything goes). Should improve interoperability.