Created
December 23, 2015 21:22
-
-
Save ddelazerda/fc6e962d3487cfef0708 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/authheader.go b/authheader.go | |
index 4ca6f1b..959a811 100644 | |
--- a/authheader.go | |
+++ b/authheader.go | |
@@ -15,6 +15,11 @@ func (h authheader) IsNegotiate() bool { | |
return strings.HasPrefix(string(h), "Negotiate") | |
} | |
+func (h authheader) IsChallenge() bool { | |
+ p := strings.Split(string(h), " ") | |
+ return len(p) == 2 && len(p[1]) > 0 && strings.HasPrefix(p[0], "NTLM") | |
+} | |
+ | |
func (h authheader) GetData() ([]byte, error) { | |
p := strings.Split(string(h), " ") | |
if len(p) < 2 { | |
diff --git a/negotiator.go b/negotiator.go | |
index 8e15558..215da31 100644 | |
--- a/negotiator.go | |
+++ b/negotiator.go | |
@@ -15,12 +15,15 @@ type Negotiator struct{ http.RoundTripper } | |
//re-sends as needed. | |
func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error) { | |
body := bytes.Buffer{} | |
- _, err = body.ReadFrom(req.Body) | |
- if err != nil { | |
- return nil, err | |
+ | |
+ if req.Body != nil { | |
+ _, err = body.ReadFrom(req.Body) | |
+ if err != nil { | |
+ return nil, err | |
+ } | |
+ req.Body.Close() | |
} | |
- req.Body.Close() | |
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes())) | |
reqauth := authheader(req.Header.Get("Authorization")) | |
@@ -65,7 +68,11 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error) | |
// send negotiate | |
negotiateMessage := NewNegotiateMessage() | |
- req.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString(negotiateMessage)) | |
+ | |
+ // format for the Authorization request header is found here: | |
+ // http://davenport.sourceforge.net/ntlm.html#ntlmHttpAuthentication | |
+ // and https://msdn.microsoft.com/en-us/library/cc237505.aspx | |
+ req.Header.Set("Authorization", "NTLM " + base64.StdEncoding.EncodeToString(negotiateMessage)) | |
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes())) | |
res, err = l.RoundTripper.RoundTrip(req) | |
@@ -73,13 +80,26 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error) | |
return nil, err | |
} | |
+ // The body contents need to be read because the default Transport | |
+ // does not attempt to reuse HTTP/1.0 or HTTP/1.1 TCP connections | |
+ // ("keep-alive") unless the Body is read to completion and is closed. | |
+ // Without this, the subsequent request will be treated as a brand new | |
+ // tcp connection, which resets the NTLM handshake. | |
+ // Reference: https://godoc.org/net/http#Response | |
+ if res.Body != nil { | |
+ _, err = body.ReadFrom(res.Body) | |
+ if err != nil { | |
+ return nil, err | |
+ } | |
+ } | |
+ | |
// receive challenge? | |
resauth = authheader(res.Header.Get("Www-Authenticate")) | |
challengeMessage, err := resauth.GetData() | |
if err != nil { | |
return nil, err | |
} | |
- if !resauth.IsNegotiate() || len(challengeMessage) == 0 { | |
+ if !resauth.IsChallenge() || len(challengeMessage) == 0 { | |
// Negotiation failed, let client deal with response | |
return res, nil | |
} | |
@@ -90,7 +110,11 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error) | |
if err != nil { | |
return nil, err | |
} | |
- req.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString(authenticateMessage)) | |
+ | |
+ // format for the Authorization request header is found here: | |
+ // http://davenport.sourceforge.net/ntlm.html#ntlmHttpAuthentication | |
+ // and https://msdn.microsoft.com/en-us/library/cc237505.aspx | |
+ req.Header.Set("Authorization", "NTLM " + base64.StdEncoding.EncodeToString(authenticateMessage)) | |
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes())) | |
res, err = l.RoundTripper.RoundTrip(req) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment