Skip to content

Commit 4a564b5

Browse files
authored
Fix HTTP proxy authentication to support both preemptive and challenge-response auth (#134)
1 parent 5b7f822 commit 4a564b5

File tree

1 file changed

+20
-16
lines changed

1 file changed

+20
-16
lines changed

http.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,23 @@ func (s *HTTPServer) authenticate(req *http.Request) (int, error) {
3131
}
3232

3333
auth := req.Header.Get(proxyAuthHeaderKey)
34-
if auth != "" {
35-
enc := strings.TrimPrefix(auth, "Basic ")
36-
str, err := base64.StdEncoding.DecodeString(enc)
37-
if err != nil {
38-
return http.StatusNotAcceptable, fmt.Errorf("decode username and password failed: %w", err)
39-
}
40-
pairs := bytes.SplitN(str, []byte(":"), 2)
41-
if len(pairs) != 2 {
42-
return http.StatusLengthRequired, fmt.Errorf("username and password format invalid")
43-
}
44-
if s.auth.Valid(string(pairs[0]), string(pairs[1])) {
45-
return 0, nil
46-
}
47-
return http.StatusUnauthorized, fmt.Errorf("username and password not matching")
34+
if auth == "" {
35+
return http.StatusProxyAuthRequired, fmt.Errorf(http.StatusText(http.StatusProxyAuthRequired))
4836
}
4937

50-
return http.StatusProxyAuthRequired, fmt.Errorf(http.StatusText(http.StatusProxyAuthRequired))
38+
enc := strings.TrimPrefix(auth, "Basic ")
39+
str, err := base64.StdEncoding.DecodeString(enc)
40+
if err != nil {
41+
return http.StatusNotAcceptable, fmt.Errorf("decode username and password failed: %w", err)
42+
}
43+
pairs := bytes.SplitN(str, []byte(":"), 2)
44+
if len(pairs) != 2 {
45+
return http.StatusLengthRequired, fmt.Errorf("username and password format invalid")
46+
}
47+
if s.auth.Valid(string(pairs[0]), string(pairs[1])) {
48+
return 0, nil
49+
}
50+
return http.StatusUnauthorized, fmt.Errorf("username and password not matching")
5151
}
5252

5353
func (s *HTTPServer) handleConn(req *http.Request, conn net.Conn) (peer net.Conn, err error) {
@@ -103,7 +103,11 @@ func (s *HTTPServer) serve(conn net.Conn) {
103103

104104
code, err := s.authenticate(req)
105105
if err != nil {
106-
_ = responseWith(req, code).Write(conn)
106+
resp := responseWith(req, code)
107+
if code == http.StatusProxyAuthRequired {
108+
resp.Header.Set("Proxy-Authenticate", "Basic realm=\"Proxy\"")
109+
}
110+
_ = resp.Write(conn)
107111
log.Println(err)
108112
return
109113
}

0 commit comments

Comments
 (0)