Files
rtsp-simple-server/internal/defs/path_access_request.go

97 lines
2.4 KiB
Go

package defs
import (
"net"
"net/http"
"net/url"
"strings"
"github.com/bluenviron/gortsplib/v4/pkg/base"
"github.com/bluenviron/gortsplib/v4/pkg/headers"
"github.com/bluenviron/mediamtx/internal/auth"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/google/uuid"
)
func addJWTFromAuthorization(rawQuery string, auth string) string {
jwt := strings.TrimPrefix(auth, "Bearer ")
if rawQuery != "" {
if v, err := url.ParseQuery(rawQuery); err == nil && v.Get("jwt") == "" {
v.Set("jwt", jwt)
return v.Encode()
}
}
return url.Values{"jwt": []string{jwt}}.Encode()
}
// PathAccessRequest is a path access request.
type PathAccessRequest struct {
Name string
Query string
Publish bool
SkipAuth bool
// only if skipAuth = false
User string
Pass string
IP net.IP
Proto auth.Protocol
ID *uuid.UUID
// RTSP only
RTSPRequest *base.Request
RTSPNonce string
}
// ToAuthRequest converts a path access request into an authentication request.
func (r *PathAccessRequest) ToAuthRequest() *auth.Request {
return &auth.Request{
User: r.User,
Pass: r.Pass,
IP: r.IP,
Action: func() conf.AuthAction {
if r.Publish {
return conf.AuthActionPublish
}
return conf.AuthActionRead
}(),
Path: r.Name,
Protocol: r.Proto,
ID: r.ID,
Query: r.Query,
RTSPRequest: r.RTSPRequest,
RTSPNonce: r.RTSPNonce,
}
}
// FillFromRTSPRequest fills User and Pass from a RTSP request.
func (r *PathAccessRequest) FillFromRTSPRequest(rt *base.Request) {
var rtspAuthHeader headers.Authorization
err := rtspAuthHeader.Unmarshal(rt.Header["Authorization"])
if err == nil {
if rtspAuthHeader.Method == headers.AuthMethodBasic {
r.User = rtspAuthHeader.BasicUser
r.Pass = rtspAuthHeader.BasicPass
} else {
r.User = rtspAuthHeader.Username
}
}
}
// FillFromHTTPRequest fills Query, User and Pass from an HTTP request.
func (r *PathAccessRequest) FillFromHTTPRequest(h *http.Request) {
r.Query = h.URL.RawQuery
r.User, r.Pass, _ = h.BasicAuth()
// move Authorization header from headers to Query
if h := h.Header.Get("Authorization"); strings.HasPrefix(h, "Bearer ") {
// support passing user and password through the Authorization header
if parts := strings.Split(strings.TrimPrefix(h, "Bearer "), ":"); len(parts) == 2 {
r.User = parts[0]
r.Pass = parts[1]
} else {
r.Query = addJWTFromAuthorization(r.Query, h)
}
}
}