From 5316b412d2ace0559450d2b6baacdb8dc9a1e8f3 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 12 Jan 2018 20:00:06 +0100 Subject: [PATCH] Fix concurrent map writes on digest auth --- Gopkg.lock | 7 ++++--- Gopkg.toml | 3 ++- docs/configuration/backends/web.md | 2 +- docs/configuration/entrypoints.md | 2 +- vendor/github.com/abbot/go-http-auth/digest.go | 13 ++++++++++--- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 326b7940b..619b529cb 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -120,10 +120,11 @@ version = "v1.0.0" [[projects]] + branch = "containous-fork" name = "github.com/abbot/go-http-auth" packages = ["."] - revision = "0ddd408d5d60ea76e320503cc7dd091992dee608" - version = "v0.4.0" + revision = "65b0cdae8d7fe5c05c7430e055938ef6d24a66c9" + source = "github.com/containous/go-http-auth" [[projects]] name = "github.com/aokoli/goutils" @@ -1385,6 +1386,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "8cd40e70454298aa3ef967edf2c501aef87f1964b9e5cef3318f2c99fc5e620e" + inputs-digest = "bd1e7a1b07d95ff85c675468bbfc4bc7a91c39cf1feceeb58dfcdba9592180a5" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 782f6cb89..4ee5b995e 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -38,8 +38,9 @@ ignored = ["github.com/sirupsen/logrus"] name = "github.com/NYTimes/gziphandler" [[constraint]] + branch = "containous-fork" name = "github.com/abbot/go-http-auth" - version = "0.4.0" + source = "github.com/containous/go-http-auth" [[constraint]] branch = "master" diff --git a/docs/configuration/backends/web.md b/docs/configuration/backends/web.md index d1363c2f5..a5e185560 100644 --- a/docs/configuration/backends/web.md +++ b/docs/configuration/backends/web.md @@ -89,7 +89,7 @@ Users can be specified directly in the toml file, or indirectly by referencing a # To enable digest auth on the webui with 2 user/realm/pass: test:traefik:test and test2:traefik:test2 [web.auth.digest] -users = ["test:traefik:a2688e031edb4be6a3797f3882655c05 ", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] +users = ["test:traefik:a2688e031edb4be6a3797f3882655c05", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] usersFile = "/path/to/.htdigest" # ... diff --git a/docs/configuration/entrypoints.md b/docs/configuration/entrypoints.md index 5a6d73ca0..a9b949f9b 100644 --- a/docs/configuration/entrypoints.md +++ b/docs/configuration/entrypoints.md @@ -136,7 +136,7 @@ Users can be specified directly in the toml file, or indirectly by referencing a [entryPoints.http] address = ":80" [entryPoints.http.auth.digest] - users = ["test:traefik:a2688e031edb4be6a3797f3882655c05 ", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] + users = ["test:traefik:a2688e031edb4be6a3797f3882655c05", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] usersFile = "/path/to/.htdigest" ``` diff --git a/vendor/github.com/abbot/go-http-auth/digest.go b/vendor/github.com/abbot/go-http-auth/digest.go index 21b09334c..0ea5bacf9 100644 --- a/vendor/github.com/abbot/go-http-auth/digest.go +++ b/vendor/github.com/abbot/go-http-auth/digest.go @@ -39,7 +39,7 @@ type DigestAuth struct { ClientCacheTolerance int clients map[string]*digest_client - mutex sync.Mutex + mutex sync.RWMutex } // check that DigestAuth implements AuthenticatorInterface @@ -84,11 +84,16 @@ func (a *DigestAuth) Purge(count int) { (or requires reauthentication). */ func (a *DigestAuth) RequireAuth(w http.ResponseWriter, r *http.Request) { + a.mutex.Lock() + defer a.mutex.Unlock() if len(a.clients) > a.ClientCacheSize+a.ClientCacheTolerance { a.Purge(a.ClientCacheTolerance * 2) } + nonce := RandomKey() + a.clients[nonce] = &digest_client{nc: 0, last_seen: time.Now().UnixNano()} + w.Header().Set(contentType, a.Headers.V().UnauthContentType) w.Header().Set(a.Headers.V().Authenticate, fmt.Sprintf(`Digest realm="%s", nonce="%s", opaque="%s", algorithm="MD5", qop="auth"`, @@ -118,8 +123,8 @@ func DigestAuthParams(authorization string) map[string]string { Authentication-Info response header. */ func (da *DigestAuth) CheckAuth(r *http.Request) (username string, authinfo *string) { - da.mutex.Lock() - defer da.mutex.Unlock() + da.mutex.RLock() + defer da.mutex.RUnlock() username = "" authinfo = nil auth := DigestAuthParams(r.Header.Get(da.Headers.V().Authorization)) @@ -242,6 +247,8 @@ func (a *DigestAuth) JustCheck(wrapped http.HandlerFunc) http.HandlerFunc { // NewContext returns a context carrying authentication information for the request. func (a *DigestAuth) NewContext(ctx context.Context, r *http.Request) context.Context { + a.mutex.Lock() + defer a.mutex.Unlock() username, authinfo := a.CheckAuth(r) info := &Info{Username: username, ResponseHeaders: make(http.Header)} if username != "" {