]> Cypherpunks repositories - gostls13.git/commitdiff
net/smtp: allow PLAIN auth when advertised
authorBrad Fitzpatrick <bradfitz@golang.org>
Wed, 3 Apr 2013 17:52:20 +0000 (10:52 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 3 Apr 2013 17:52:20 +0000 (10:52 -0700)
The smtp package originally allowed PLAIN whenever, but then
the TLS check was added for paranoia, but it's too paranoid:
it prevents using PLAIN auth even from localhost to localhost
when the server advertises PLAIN support.

This CL also permits the client to send PLAIN if the server
advertises it.

Fixes #5184

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/8279043

src/pkg/net/smtp/auth.go
src/pkg/net/smtp/smtp_test.go

index d401e3c21fd0721e87c0a66594328b2049dacd2b..3f1339ebc56e299a70ddc8644db651c9d9c01f24 100644 (file)
@@ -54,7 +54,16 @@ func PlainAuth(identity, username, password, host string) Auth {
 
 func (a *plainAuth) Start(server *ServerInfo) (string, []byte, error) {
        if !server.TLS {
-               return "", nil, errors.New("unencrypted connection")
+               advertised := false
+               for _, mechanism := range server.Auth {
+                       if mechanism == "PLAIN" {
+                               advertised = true
+                               break
+                       }
+               }
+               if !advertised {
+                       return "", nil, errors.New("unencrypted connection")
+               }
        }
        if server.Name != a.host {
                return "", nil, errors.New("wrong host name")
index 8317428cb8706818dd8de2fe762064d37be22918..c190b32c05441d51bec0929eaaae9ba86eeb7d18 100644 (file)
@@ -57,6 +57,41 @@ testLoop:
        }
 }
 
+func TestAuthPlain(t *testing.T) {
+       auth := PlainAuth("foo", "bar", "baz", "servername")
+
+       tests := []struct {
+               server *ServerInfo
+               err    string
+       }{
+               {
+                       server: &ServerInfo{Name: "servername", TLS: true},
+               },
+               {
+                       // Okay; explicitly advertised by server.
+                       server: &ServerInfo{Name: "servername", Auth: []string{"PLAIN"}},
+               },
+               {
+                       server: &ServerInfo{Name: "servername", Auth: []string{"CRAM-MD5"}},
+                       err:    "unencrypted connection",
+               },
+               {
+                       server: &ServerInfo{Name: "attacker", TLS: true},
+                       err:    "wrong host name",
+               },
+       }
+       for i, tt := range tests {
+               _, _, err := auth.Start(tt.server)
+               got := ""
+               if err != nil {
+                       got = err.Error()
+               }
+               if got != tt.err {
+                       t.Errorf("%d. got error = %q; want %q", i, got, tt.err)
+               }
+       }
+}
+
 type faker struct {
        io.ReadWriter
 }