From fb7852951705df4d2a881aba0531760e95888450 Mon Sep 17 00:00:00 2001 From: Brian Dwyer Date: Sat, 18 Apr 2020 13:43:11 -0400 Subject: [PATCH 1/2] Address concurrency issues reading/writing header values --- basic.go | 4 ++-- connect.go | 4 ++-- negotiate_windows.go | 4 ++-- ntlm_other.go | 8 ++++---- ntlm_windows.go | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/basic.go b/basic.go index 1a37e5d..2bfd0c5 100644 --- a/basic.go +++ b/basic.go @@ -20,14 +20,14 @@ func dialBasic(p Proxy, addr string, baseDial func() (net.Conn, error)) (net.Con } u := fmt.Sprintf("%s:%s", p.Username, p.Password) - h := p.Headers + h := p.Headers.Clone() h.Set("Proxy-Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(u)))) h.Set("Proxy-Connection", "Keep-Alive") connect := &http.Request{ Method: "CONNECT", URL: &url.URL{Opaque: addr}, Host: addr, - Header: *h, + Header: h, } if err := connect.Write(conn); err != nil { debugf("basic> Could not write authorization message to proxy: %s", err) diff --git a/connect.go b/connect.go index 61eeddf..009640b 100644 --- a/connect.go +++ b/connect.go @@ -18,13 +18,13 @@ func dialAndNegotiateHTTP(p Proxy, addr string, baseDial func() (net.Conn, error } // build and write first CONNECT request - h := p.Headers + h := p.Headers.Clone() h.Set("Proxy-Connection", "Keep-Alive") connect := &http.Request{ Method: "CONNECT", URL: &url.URL{Opaque: addr}, Host: addr, - Header: *p.Headers, + Header: h, } if err := connect.Write(conn); err != nil { debugf("connect> CONNECT to proxy failed: %s", err) diff --git a/negotiate_windows.go b/negotiate_windows.go index 0fadae1..015969b 100644 --- a/negotiate_windows.go +++ b/negotiate_windows.go @@ -49,14 +49,14 @@ func dialNegotiate(p Proxy, addr string, baseDial func() (net.Conn, error)) (net } defer secctx.Release() - head := p.Headers + head := p.Headers.Clone() head.Set("Proxy-Authorization", fmt.Sprintf("Negotiate %s", base64.StdEncoding.EncodeToString(token))) head.Set("Proxy-Connection", "Keep-Alive") connect := &http.Request{ Method: "CONNECT", URL: &url.URL{Opaque: addr}, Host: addr, - Header: *head, + Header: head, } if err := connect.Write(conn); err != nil { debugf("negotiate> Could not write token message to proxy: %s", err) diff --git a/ntlm_other.go b/ntlm_other.go index 16534f3..690b014 100644 --- a/ntlm_other.go +++ b/ntlm_other.go @@ -68,14 +68,14 @@ func dialNTLM(p Proxy, addr string, baseDial func() (net.Conn, error)) (net.Conn return conn, err } - h := p.Headers + h := p.Headers.Clone() h.Set("Proxy-Authorization", fmt.Sprintf("NTLM %s", base64.StdEncoding.EncodeToString(negotiateNTLMv1Message()))) h.Set("Proxy-Connection", "Keep-Alive") connect := &http.Request{ Method: "CONNECT", URL: &url.URL{Opaque: addr}, Host: addr, - Header: *h, + Header: h, } if err := connect.Write(conn); err != nil { debugf("ntlm> Could not write negotiate message to proxy: %s", err) @@ -126,14 +126,14 @@ func dialNTLM(p Proxy, addr string, baseDial func() (net.Conn, error)) (net.Conn } resp.Body.Close() - h = p.Headers + h = p.Headers.Clone() h.Set("Proxy-Authorization", fmt.Sprintf("NTLM %s", base64.StdEncoding.EncodeToString(authenticate.Bytes()))) h.Set("Proxy-Connection", "Keep-Alive") connect = &http.Request{ Method: "CONNECT", URL: &url.URL{Opaque: addr}, Host: addr, - Header: *h, + Header: h, } if err := connect.Write(conn); err != nil { debugf("ntlm> Could not write authenticate message to proxy: %s", err) diff --git a/ntlm_windows.go b/ntlm_windows.go index 9d3e3d1..fe59578 100644 --- a/ntlm_windows.go +++ b/ntlm_windows.go @@ -45,14 +45,14 @@ func dialNTLM(p Proxy, addr string, baseDial func() (net.Conn, error)) (net.Conn } defer secctx.Release() - h := p.Headers + h := p.Headers.Clone() h.Set("Proxy-Authorization", fmt.Sprintf("NTLM %s", base64.StdEncoding.EncodeToString(negotiate))) h.Set("Proxy-Connection", "Keep-Alive") connect := &http.Request{ Method: "CONNECT", URL: &url.URL{Opaque: addr}, Host: addr, - Header: *h, + Header: h, } if err := connect.Write(conn); err != nil { debugf("ntlm> Could not write negotiate message to proxy: %s", err) @@ -83,14 +83,14 @@ func dialNTLM(p Proxy, addr string, baseDial func() (net.Conn, error)) (net.Conn } resp.Body.Close() - h = p.Headers + h = p.Headers.Clone() h.Set("Proxy-Authorization", fmt.Sprintf("NTLM %s", base64.StdEncoding.EncodeToString(authenticate))) h.Set("Proxy-Connection", "Keep-Alive") connect = &http.Request{ Method: "CONNECT", URL: &url.URL{Opaque: addr}, Host: addr, - Header: *h, + Header: h, } if err := connect.Write(conn); err != nil { debugf("ntlm> Could not write authenticate message to proxy: %s", err) From 20a87f0335a251b321aeb43b41fcd9beaec302c0 Mon Sep 17 00:00:00 2001 From: Brian Dwyer Date: Sat, 18 Apr 2020 13:43:34 -0400 Subject: [PATCH 2/2] Address out of bounds panic on Proxy-Authenticate header Signed-off-by: Brian Dwyer --- ntlm_windows.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ntlm_windows.go b/ntlm_windows.go index fe59578..7d1436b 100644 --- a/ntlm_windows.go +++ b/ntlm_windows.go @@ -10,6 +10,7 @@ import ( "net" "net/http" "net/url" + "strings" "github.com/alexbrainman/sspi" "github.com/alexbrainman/sspi/ntlm" @@ -70,7 +71,18 @@ func dialNTLM(p Proxy, addr string, baseDial func() (net.Conn, error)) (net.Conn return conn, errors.New("Unexpected HTTP status code") } - challenge, err := base64.StdEncoding.DecodeString(resp.Header["Proxy-Authenticate"][0][5:]) + challengeHeaders, found := resp.Header["Proxy-Authenticate"] + if !found { + return conn, errors.New("did not receive a challenge from the server") + } + if len(challengeHeaders) != 1 { + return conn, errors.New("received malformed challenge from the server") + } + if len(challengeHeaders[0]) < 6 || !strings.HasPrefix(challengeHeaders[0], "NTLM ") { + return conn, errors.New("received malformed challenge from the server") + } + + challenge, err := base64.StdEncoding.DecodeString(challengeHeaders[0][5:]) if err != nil { debugf("ntlm> Could not read challenge response") return conn, err