From bde2d861e7e49caf445873ee2ef999fd6f443de1 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Fri, 31 Jan 2020 10:12:35 +0100 Subject: [PATCH 1/2] Remove 'check' variable There was a bug that if an empty token was ever passed in, all subsequent usage of ListenAndServe would skip the check. We should just remove this global and reject empty tokens. --- nanoauth.go | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/nanoauth.go b/nanoauth.go index dbe3fc3..151ca00 100644 --- a/nanoauth.go +++ b/nanoauth.go @@ -6,6 +6,7 @@ package nanoauth import ( "crypto/tls" + "errors" "net" "net/http" ) @@ -22,9 +23,6 @@ type Auth struct { var ( // DefaultAuth is the default Auth object DefaultAuth = &Auth{} - - // whether or not to check auth tokens - check = true ) func init() { @@ -34,7 +32,7 @@ func init() { // ServeHTTP is to implement the http.Handler interface. Also let clients know // when I have no matching route listeners -func (self Auth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { +func (self *Auth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { reqPath := req.URL.Path skipOnce := false @@ -51,7 +49,7 @@ func (self Auth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { skipOnce = true } - if !skipOnce && check { + if !skipOnce { auth := "" if auth = req.Header.Get(self.Header); auth == "" { // check form value (case sensitive) if header not set @@ -69,6 +67,9 @@ func (self Auth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { // ListenAndServeTLS starts a TLS listener and handles serving https func (self *Auth) ListenAndServeTLS(addr, token string, h http.Handler, excludedPaths ...string) error { + if token == "" { + return errors.New("nanoauth: token missing") + } config := &tls.Config{ Certificates: []tls.Certificate{*self.Certificate}, } @@ -78,9 +79,6 @@ func (self *Auth) ListenAndServeTLS(addr, token string, h http.Handler, excluded return err } - if token == "" { - check = false - } self.ExcludedPaths = excludedPaths self.Token = token @@ -95,14 +93,14 @@ func (self *Auth) ListenAndServeTLS(addr, token string, h http.Handler, excluded // ListenAndServe starts a normal tcp listener and handles serving http while // still validating the auth token. func (self *Auth) ListenAndServe(addr, token string, h http.Handler, excludedPaths ...string) error { + if token == "" { + return errors.New("nanoauth: token missing") + } httpListener, err := net.Listen("tcp", addr) if err != nil { return err } - if token == "" { - check = false - } self.ExcludedPaths = excludedPaths self.Token = token From f6d0792ec349afea59b2f3f92b11412852cbaa27 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Fri, 31 Jan 2020 10:28:42 +0100 Subject: [PATCH 2/2] Use constant-time comparison to prevent timing attacks --- nanoauth.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nanoauth.go b/nanoauth.go index 151ca00..33f9c22 100644 --- a/nanoauth.go +++ b/nanoauth.go @@ -5,6 +5,7 @@ package nanoauth import ( + "crypto/subtle" "crypto/tls" "errors" "net" @@ -56,7 +57,7 @@ func (self *Auth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { auth = req.FormValue(self.Header) } - if auth != self.Token { + if subtle.ConstantTimeCompare([]byte(auth), []byte(self.Token)) == 0 { rw.WriteHeader(http.StatusUnauthorized) return }