mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2026-10-01 12:11:19 +02:00
* update to release version v7.15.5 * Merge commit from fork Signed-off-by: Jan Larwig <jan@larwig.com> Co-authored-by: blakeroberts-wk <blake.roberts@workiva.com> * Merge commit from fork Signed-off-by: Jan Larwig <jan@larwig.com> * Merge commit from fork * fix: validate trusted IP proxy headers Respect trusted proxy boundaries before using real-client-IP headers for authentication bypass decisions and safely traverse X-Forwarded-For chains. Signed-off-by: Jan Larwig <jan@larwig.com> * fix: trusted-ip header bypass Signed-off-by: Jan Larwig <jan@larwig.com> * docs: add changelog entry Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> --------- Signed-off-by: Jan Larwig <jan@larwig.com> Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> * docs: changelog for v7.15.5 Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> * docs: update order of owners for prow Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> * ci: make the linter happy again Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> --------- Signed-off-by: Jan Larwig <jan@larwig.com> Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Jan Larwig <jan@larwig.com> Co-authored-by: blakeroberts-wk <blake.roberts@workiva.com> Co-authored-by: Jan Larwig <jan.larwig@digits.schwarz>
95 lines
2.8 KiB
Go
95 lines
2.8 KiB
Go
package util
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
|
|
middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
|
|
)
|
|
|
|
const (
|
|
XForwardedProto = "X-Forwarded-Proto"
|
|
XForwardedHost = "X-Forwarded-Host"
|
|
XForwardedURI = "X-Forwarded-Uri"
|
|
)
|
|
|
|
// GetRequestProto returns the request scheme or X-Forwarded-Proto if present
|
|
// and the request came from a trusted reverse proxy.
|
|
func GetRequestProto(req *http.Request) string {
|
|
proto := req.Header.Get(XForwardedProto)
|
|
if !CanTrustForwardedHeaders(req) || proto == "" {
|
|
proto = req.URL.Scheme
|
|
}
|
|
return proto
|
|
}
|
|
|
|
// GetRequestHost returns the request host header or X-Forwarded-Host if
|
|
// present and the request came from a trusted reverse proxy.
|
|
func GetRequestHost(req *http.Request) string {
|
|
host := req.Header.Get(XForwardedHost)
|
|
if !CanTrustForwardedHeaders(req) || host == "" {
|
|
host = req.Host
|
|
}
|
|
return host
|
|
}
|
|
|
|
// GetRequestURI return the request URI or X-Forwarded-Uri if present and the
|
|
// request came from a trusted reverse proxy.
|
|
func GetRequestURI(req *http.Request) string {
|
|
uri := req.Header.Get(XForwardedURI)
|
|
if !CanTrustForwardedHeaders(req) || uri == "" {
|
|
// Use RequestURI to preserve ?query
|
|
uri = req.URL.RequestURI()
|
|
}
|
|
return uri
|
|
}
|
|
|
|
// GetRequestPath returns a decoded path suitable for skip-auth matching, using
|
|
// X-Forwarded-Uri only for a trusted reverse proxy. An error means the path must
|
|
// not grant an authentication exemption. It does not modify the request URL.
|
|
func GetRequestPath(req *http.Request) (string, error) {
|
|
uri := GetRequestURI(req)
|
|
if !strings.HasPrefix(uri, "/") || strings.ContainsAny(uri, "# \t\r\n") {
|
|
return "", errors.New("request target is not an unambiguous origin-form URI")
|
|
}
|
|
|
|
// Unlike url.Parse, ParseRequestURI keeps a leading // in the path.
|
|
parsedURL, err := url.ParseRequestURI(uri)
|
|
if err != nil {
|
|
return "", errors.New("invalid request target")
|
|
}
|
|
requestPath := parsedURL.Path
|
|
if strings.ContainsAny(requestPath, ";\\#?") || strings.Contains(requestPath, "//") {
|
|
return "", errors.New("request path contains ambiguous separators")
|
|
}
|
|
for _, char := range requestPath {
|
|
if char < 0x20 || char == 0x7f {
|
|
return "", errors.New("request path contains a control character")
|
|
}
|
|
}
|
|
for _, segment := range strings.Split(requestPath, "/") {
|
|
if segment == "." || segment == ".." {
|
|
return "", errors.New("request path contains a dot segment")
|
|
}
|
|
}
|
|
return requestPath, nil
|
|
}
|
|
|
|
// CanTrustForwardedHeaders determines if forwarded headers should be processed
|
|
// based on the RequestScope and the direct caller's address.
|
|
func CanTrustForwardedHeaders(req *http.Request) bool {
|
|
scope := middlewareapi.GetRequestScope(req)
|
|
if scope == nil {
|
|
return false
|
|
}
|
|
|
|
return scope.CanTrustForwardedHeaders(req)
|
|
}
|
|
|
|
func IsForwardedRequest(req *http.Request) bool {
|
|
return CanTrustForwardedHeaders(req) &&
|
|
req.Host != GetRequestHost(req)
|
|
}
|