mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-23 15:36:47 +00:00
# Which Problems Are Solved Host headers used to identify the instance and further used in public responses such as OIDC discovery endpoints, email links and more were not correctly handled. While they were matched against existing instances, they were not properly sanitized. # How the Problems Are Solved Sanitize host header including port validation (if provided). # Additional Changes None # Additional Context - requires backports (cherry picked from commit72a5c33e6a) (cherry picked from commit7520450e11)
91 lines
2.1 KiB
Go
91 lines
2.1 KiB
Go
package http
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"net/url"
|
|
)
|
|
|
|
type DomainCtx struct {
|
|
InstanceHost string
|
|
PublicHost string
|
|
Protocol string
|
|
}
|
|
|
|
func NewDomainCtx(instanceHostname, publicHostname, protocol string) *DomainCtx {
|
|
return &DomainCtx{
|
|
InstanceHost: instanceHostname,
|
|
PublicHost: publicHostname,
|
|
Protocol: protocol,
|
|
}
|
|
}
|
|
|
|
func NewDomainCtxFromOrigin(origin *url.URL) *DomainCtx {
|
|
return &DomainCtx{
|
|
InstanceHost: origin.Host,
|
|
PublicHost: origin.Host,
|
|
Protocol: origin.Scheme,
|
|
}
|
|
}
|
|
|
|
// InstanceDomain returns the hostname for which the request was handled.
|
|
func (r *DomainCtx) InstanceDomain() string {
|
|
return hostnameFromHost(r.InstanceHost)
|
|
}
|
|
|
|
func hostnameFromHost(host string) string {
|
|
hostname, _, err := net.SplitHostPort(host)
|
|
if err != nil {
|
|
return host
|
|
}
|
|
return hostname
|
|
}
|
|
|
|
// RequestedHost returns the host (hostname[:port]) for which the request was handled.
|
|
// The instance host is returned if not public host was set.
|
|
func (r *DomainCtx) RequestedHost() string {
|
|
if r.PublicHost != "" {
|
|
return r.PublicHost
|
|
}
|
|
return r.InstanceHost
|
|
}
|
|
|
|
// RequestedDomain returns the domain (hostname) for which the request was handled.
|
|
// The instance domain is returned if no public host / domain was set.
|
|
func (r *DomainCtx) RequestedDomain() string {
|
|
return hostnameFromHost(r.RequestedHost())
|
|
}
|
|
|
|
// Origin returns the origin (protocol://hostname[:port]) for which the request was handled.
|
|
// The instance host is used if no public host was set.
|
|
func (r *DomainCtx) Origin() string {
|
|
host := r.PublicHost
|
|
if host == "" {
|
|
host = r.InstanceHost
|
|
}
|
|
return fmt.Sprintf("%s://%s", r.Protocol, host)
|
|
}
|
|
|
|
func DomainContext(ctx context.Context) *DomainCtx {
|
|
o, ok := ctx.Value(domainCtx).(*DomainCtx)
|
|
if !ok {
|
|
return &DomainCtx{}
|
|
}
|
|
return o
|
|
}
|
|
|
|
func WithDomainContext(ctx context.Context, domainContext *DomainCtx) context.Context {
|
|
return context.WithValue(ctx, domainCtx, domainContext)
|
|
}
|
|
|
|
func WithRequestedHost(ctx context.Context, host string) context.Context {
|
|
i, ok := ctx.Value(domainCtx).(*DomainCtx)
|
|
if !ok {
|
|
i = new(DomainCtx)
|
|
}
|
|
|
|
i.PublicHost = host
|
|
return context.WithValue(ctx, domainCtx, i)
|
|
}
|