1
0
mirror of https://github.com/distribution/distribution synced 2024-11-06 19:35:52 +01:00

Fix missing auth headers with PATCH HTTP request when pushing to default port

If a user specifies `mydomain.com:443` in the `Host` configuration, the
PATCH request for the layer upload will fail because the challenge does not
appear to be in the map. To fix this, we normalize the map keys to always
use the Host:Port combination.

Closes https://github.com/docker/docker/issues/18469

Signed-off-by: Stan Hu <stanhu@gmail.com>
This commit is contained in:
Stan Hu 2016-09-01 14:46:31 -07:00
parent 7dcac52f18
commit 462bb55c3f
3 changed files with 37 additions and 2 deletions

@ -0,0 +1,27 @@
package auth
import (
"net/url"
"strings"
)
// FROM: http://golang.org/src/net/http/client.go
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// FROM: http://golang.org/src/net/http/transport.go
var portMap = map[string]string{
"http": "80",
"https": "443",
}
// CanonicalAddr returns url.Host but always with a ":port" suffix
// FROM: http://golang.org/src/net/http/transport.go
func CanonicalAddr(url *url.URL) string {
addr := url.Host
if !hasPort(addr) {
return addr + ":" + portMap[url.Scheme]
}
return addr
}

@ -54,8 +54,13 @@ type simpleChallengeManager struct {
Challanges map[string][]Challenge
}
func (m *simpleChallengeManager) GetChallenges(endpoint url.URL) ([]Challenge, error) {
func normalizeURL(endpoint *url.URL) {
endpoint.Host = strings.ToLower(endpoint.Host)
endpoint.Host = CanonicalAddr(endpoint)
}
func (m *simpleChallengeManager) GetChallenges(endpoint url.URL) ([]Challenge, error) {
normalizeURL(&endpoint)
m.RLock()
defer m.RUnlock()
@ -70,11 +75,12 @@ func (m *simpleChallengeManager) AddResponse(resp *http.Response) error {
}
urlCopy := url.URL{
Path: resp.Request.URL.Path,
Host: strings.ToLower(resp.Request.URL.Host),
Host: resp.Request.URL.Host,
Scheme: resp.Request.URL.Scheme,
}
m.Lock()
defer m.Unlock()
normalizeURL(&urlCopy)
m.Challanges[urlCopy.String()] = challenges
return nil
}

@ -44,6 +44,7 @@ func TestAuthChallengeParse(t *testing.T) {
func TestAuthChallengeNormalization(t *testing.T) {
testAuthChallengeNormalization(t, "reg.EXAMPLE.com")
testAuthChallengeNormalization(t, "bɿɒʜɔiɿ-ɿɘƚƨim-ƚol-ɒ-ƨʞnɒʜƚ.com")
testAuthChallengeNormalization(t, "reg.example.com:80")
testAuthChallengeConcurrent(t, "reg.EXAMPLE.com")
}
@ -72,6 +73,7 @@ func testAuthChallengeNormalization(t *testing.T, host string) {
lowered := *url
lowered.Host = strings.ToLower(lowered.Host)
lowered.Host = CanonicalAddr(&lowered)
c, err := scm.GetChallenges(lowered)
if err != nil {
t.Fatal(err)