]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: Fix basic authentication with empty password
authorAlberto GarcĂ­a Hierro <alberto@garciahierro.com>
Tue, 14 May 2013 22:33:46 +0000 (15:33 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 14 May 2013 22:33:46 +0000 (15:33 -0700)
        The encoded string must include the : separating the username
        and the password, even when the latter is empty. See
        http://www.ietf.org/rfc/rfc2617.txt for more information.

R=golang-dev, bradfitz, adg
CC=golang-dev
https://golang.org/cl/8475043

src/pkg/net/http/client.go
src/pkg/net/http/client_test.go

index a34d47be1fa7ed142f073ad1952d2c93189505aa..828422f84c3efa17c1cd0edcacc52c5502321840 100644 (file)
@@ -161,7 +161,18 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
        }
 
        if u := req.URL.User; u != nil {
-               req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(u.String())))
+               auth := u.String()
+               // UserInfo.String() only returns the colon when the
+               // password is set, so we must add it here.
+               //
+               // See 2 (end of page 4) http://www.ietf.org/rfc/rfc2617.txt
+               // "To receive authorization, the client sends the userid and password,
+               // separated by a single colon (":") character, within a base64
+               // encoded string in the credentials."
+               if _, hasPassword := u.Password(); !hasPassword {
+                       auth += ":"
+               }
+               req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(auth)))
        }
        resp, err = t.RoundTrip(req)
        if err != nil {
index 73f1fe3c10ad65d253e1d74b58b6a7482322ec4c..e82fafd57f3769961d353b1d998ea523f11f329f 100644 (file)
@@ -10,6 +10,7 @@ import (
        "bytes"
        "crypto/tls"
        "crypto/x509"
+       "encoding/base64"
        "errors"
        "fmt"
        "io"
@@ -700,3 +701,37 @@ func TestClientHeadContentLength(t *testing.T) {
                }
        }
 }
+
+func TestEmptyPasswordAuth(t *testing.T) {
+       defer afterTest(t)
+       gopher := "gopher"
+       ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+               auth := r.Header.Get("Authorization")
+               if strings.HasPrefix(auth, "Basic ") {
+                       encoded := auth[6:]
+                       decoded, err := base64.StdEncoding.DecodeString(encoded)
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+                       expected := gopher + ":"
+                       s := string(decoded)
+                       if expected != s {
+                               t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected)
+                       }
+               } else {
+                       t.Errorf("Invalid auth %q", auth)
+               }
+       }))
+       defer ts.Close()
+       c := &Client{}
+       req, err := NewRequest("GET", ts.URL, nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       req.URL.User = url.User(gopher)
+       resp, err := c.Do(req)
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer resp.Body.Close()
+}