Repository: emersion/go-smtp
Pull request #94 (2020-05-08 13:21:15)

server: Return 501 on SASL negotiation cancel

codecov[bot]: # [Codecov](https://codecov.io/gh/emersion/go-smtp/pull/94?src=pr&el=h1) Report
> Merging [#94](https://codecov.io/gh/emersion/go-smtp/pull/94?src=pr&el=desc) into [master](https://codecov.io/gh/emersion/go-smtp/commit/f9be832b55540d4ef8654697f378579ff3ca7cc0&el=desc) will **increase** coverage by `0.11%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/emersion/go-smtp/pull/94/graphs/tree.svg?width=650&height=150&src=pr&token=vj7HO8ABwC)](https://codecov.io/gh/emersion/go-smtp/pull/94?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master      #94      +/-   ##
==========================================
+ Coverage   63.36%   63.48%   +0.11%     
==========================================
  Files           8        8              
  Lines         920      923       +3     
==========================================
+ Hits          583      586       +3     
  Misses        251      251              
  Partials       86       86              
```


| [Impacted Files](https://codecov.io/gh/emersion/go-smtp/pull/94?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [conn.go](https://codecov.io/gh/emersion/go-smtp/pull/94/diff?src=pr&el=tree#diff-Y29ubi5nbw==) | `60.91% <100.00%> (+0.28%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/emersion/go-smtp/pull/94?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/emersion/go-smtp/pull/94?src=pr&el=footer). Last update [f9be832...1cf8de3](https://codecov.io/gh/emersion/go-smtp/pull/94?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/conn.go b/conn.go
index 90c0a0c..592e53a 100644
--- a/conn.go
+++ b/conn.go
@@ -454,6 +454,12 @@ func (c *Conn) handleAuth(arg string) {
 			return // TODO: error handling
 		}
 
+		if encoded == "*" {
+			// https://tools.ietf.org/html/rfc4954#page-4
+			c.WriteResponse(501, EnhancedCode{5, 0, 0}, "Negotiation cancelled")
+			return
+		}
+
 		response, err = base64.StdEncoding.DecodeString(encoded)
 		if err != nil {
 			c.WriteResponse(454, EnhancedCode{4, 7, 0}, "Invalid base64 data")


Test patch:
diff --git a/server_test.go b/server_test.go
index b575c7d..c5e00ae 100644
--- a/server_test.go
+++ b/server_test.go
@@ -239,6 +239,28 @@ func testServerAuthenticated(t *testing.T) (be *backend, s *smtp.Server, c net.C
 	return
 }
 
+func TestServerCancelSASL(t *testing.T) {
+	_, _, c, scanner, caps := testServerEhlo(t)
+
+	if _, ok := caps["AUTH PLAIN"]; !ok {
+		t.Fatal("AUTH PLAIN capability is missing when auth is enabled")
+	}
+
+	io.WriteString(c, "AUTH PLAIN\r\n")
+	scanner.Scan()
+	if scanner.Text() != "334 " {
+		t.Fatal("Invalid AUTH response:", scanner.Text())
+	}
+
+	io.WriteString(c, "*\r\n")
+	scanner.Scan()
+	if !strings.HasPrefix(scanner.Text(), "501 ") {
+		t.Fatal("Invalid AUTH response:", scanner.Text())
+	}
+
+	return
+}
+
 func TestServerEmptyFrom1(t *testing.T) {
 	_, s, c, scanner := testServerAuthenticated(t)
 	defer s.Close()