Skip to content

Commit

Permalink
fix authentication with cameras that don't support explicit algorithm (
Browse files Browse the repository at this point in the history
  • Loading branch information
aler9 committed May 3, 2024
1 parent 8b51ca9 commit d21c559
Show file tree
Hide file tree
Showing 12 changed files with 30 additions and 55 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/abema/go-mp4 v1.2.0
github.com/alecthomas/kong v0.9.0
github.com/bluenviron/gohlslib v1.3.1
github.com/bluenviron/gortsplib/v4 v4.8.2
github.com/bluenviron/gortsplib/v4 v4.8.3-0.20240503213951-d8936744aa22
github.com/bluenviron/mediacommon v1.9.3
github.com/datarhei/gosrt v0.6.0
github.com/fsnotify/fsnotify v1.7.0
Expand All @@ -24,7 +24,7 @@ require (
github.com/pion/interceptor v0.1.29
github.com/pion/logging v0.2.2
github.com/pion/rtcp v1.2.14
github.com/pion/rtp v1.8.6
github.com/pion/rtp v1.8.7-0.20240429002300-bc5124c9d0d0
github.com/pion/sdp/v3 v3.0.9
github.com/pion/webrtc/v3 v3.2.22
github.com/stretchr/testify v1.9.0
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c h1:8XZeJrs4+ZYh
github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c/go.mod h1:x1vxHcL/9AVzuk5HOloOEPrtJY0MaalYr78afXZ+pWI=
github.com/bluenviron/gohlslib v1.3.1 h1:87JEFXWfvSlfwYBX6JSCxsu+fr4zuBgk82Y4qgx0g5E=
github.com/bluenviron/gohlslib v1.3.1/go.mod h1:wD8ysO6HB90d17sxoIQXGHINo2KYj/mZirMnPtKLJZQ=
github.com/bluenviron/gortsplib/v4 v4.8.2 h1:/26wbmRv05owUsn9sa1pAdgPAlpUpbnzgBnqs1ilwWE=
github.com/bluenviron/gortsplib/v4 v4.8.2/go.mod h1:0NJSk7p8YV4zt1KdcaNwZ3CyXKAKrjUtavStCZaYjyw=
github.com/bluenviron/gortsplib/v4 v4.8.3-0.20240503213951-d8936744aa22 h1:I/58+6Tpcm061fyARIt4k80WEyGOfwX4OLgbwO0lVFs=
github.com/bluenviron/gortsplib/v4 v4.8.3-0.20240503213951-d8936744aa22/go.mod h1:WpYvpqPNJFQu0C6MVDFms2UCKFM/nGW1HvifYvLWWoA=
github.com/bluenviron/mediacommon v1.9.3 h1:qpY7m26aXdTW9SgcOHLJXazd4Jr4rle6IH2RFuQkUvE=
github.com/bluenviron/mediacommon v1.9.3/go.mod h1:0z/KHiSTlaAB8FoyW+mYulZRG70Kupcy/0yZZkgLe5M=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
Expand Down Expand Up @@ -150,8 +150,8 @@ github.com/pion/rtcp v1.2.14 h1:KCkGV3vJ+4DAJmvP0vaQShsb0xkRfWkO540Gy102KyE=
github.com/pion/rtcp v1.2.14/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
github.com/pion/rtp v1.8.2/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
github.com/pion/rtp v1.8.6 h1:MTmn/b0aWWsAzux2AmP8WGllusBVw4NPYPVFFd7jUPw=
github.com/pion/rtp v1.8.6/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
github.com/pion/rtp v1.8.7-0.20240429002300-bc5124c9d0d0 h1:yPAphilskTN7U3URvBVxlVr0PzheMeWqo7PaOqh//Hg=
github.com/pion/rtp v1.8.7-0.20240429002300-bc5124c9d0d0/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0=
github.com/pion/sctp v1.8.8 h1:5EdnnKI4gpyR1a1TwbiS/wxEgcUWBHsc7ILAjARJB+U=
github.com/pion/sctp v1.8.8/go.mod h1:igF9nZBrjh5AtmKc7U30jXltsFHicFCXSmWA2GWRaWs=
Expand Down
16 changes: 5 additions & 11 deletions internal/auth/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ type Request struct {
ID *uuid.UUID
Query string
RTSPRequest *base.Request
RTSPBaseURL *base.URL
RTSPNonce string
}

Expand Down Expand Up @@ -111,7 +110,7 @@ type Manager struct {
HTTPExclude []conf.AuthInternalUserPermission
JWTJWKS string
ReadTimeout time.Duration
RTSPAuthMethods []headers.AuthMethod
RTSPAuthMethods []auth.ValidateMethod

mutex sync.RWMutex
jwtHTTPClient *http.Client
Expand All @@ -138,19 +137,15 @@ func (m *Manager) Authenticate(req *Request) error {
func (m *Manager) authenticateInner(req *Request) error {
// if this is a RTSP request, fill username and password
var rtspAuthHeader headers.Authorization

if req.RTSPRequest != nil {
err := rtspAuthHeader.Unmarshal(req.RTSPRequest.Header["Authorization"])
if err == nil {
switch rtspAuthHeader.Method {
case headers.AuthBasic:
if rtspAuthHeader.Method == headers.AuthMethodBasic {
req.User = rtspAuthHeader.BasicUser
req.Pass = rtspAuthHeader.BasicPass

case headers.AuthDigestMD5:
} else { // digest
req.User = rtspAuthHeader.Username

default:
return fmt.Errorf("unsupported RTSP authentication method")
}
}
}
Expand Down Expand Up @@ -198,12 +193,11 @@ func (m *Manager) authenticateWithUser(
}

if u.User != "any" {
if req.RTSPRequest != nil && rtspAuthHeader.Method == headers.AuthDigestMD5 {
if req.RTSPRequest != nil && rtspAuthHeader.Method == headers.AuthMethodDigest {
err := auth.Validate(
req.RTSPRequest,
string(u.User),
string(u.Pass),
req.RTSPBaseURL,
m.RTSPAuthMethods,
rtspAuthRealm,
req.RTSPNonce)
Expand Down
5 changes: 2 additions & 3 deletions internal/auth/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/MicahParks/jwkset"
"github.com/bluenviron/gortsplib/v4/pkg/auth"
"github.com/bluenviron/gortsplib/v4/pkg/base"
"github.com/bluenviron/gortsplib/v4/pkg/headers"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -157,14 +156,14 @@ func TestAuthInternalRTSPDigest(t *testing.T) {
},
},
HTTPAddress: "",
RTSPAuthMethods: []headers.AuthMethod{headers.AuthDigestMD5},
RTSPAuthMethods: []auth.ValidateMethod{auth.ValidateMethodDigestMD5},
}

u, err := base.ParseURL("rtsp://127.0.0.1:8554/mypath")
require.NoError(t, err)

s, err := auth.NewSender(
auth.GenerateWWWAuthenticate([]headers.AuthMethod{headers.AuthDigestMD5}, "IPCAM", "mynonce"),
auth.GenerateWWWAuthenticate([]auth.ValidateMethod{auth.ValidateMethodDigestMD5}, "IPCAM", "mynonce"),
"myuser",
"mypass",
)
Expand Down
8 changes: 4 additions & 4 deletions internal/conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

"github.com/bluenviron/gohlslib"
"github.com/bluenviron/gortsplib/v4"
"github.com/bluenviron/gortsplib/v4/pkg/headers"
"github.com/bluenviron/gortsplib/v4/pkg/auth"

"github.com/bluenviron/mediamtx/internal/conf/decrypt"
"github.com/bluenviron/mediamtx/internal/conf/env"
Expand Down Expand Up @@ -47,7 +47,7 @@ func firstThatExists(paths []string) string {
return ""
}

func contains(list []headers.AuthMethod, item headers.AuthMethod) bool {
func contains(list []auth.ValidateMethod, item auth.ValidateMethod) bool {
for _, i := range list {
if i == item {
return true
Expand Down Expand Up @@ -357,7 +357,7 @@ func (conf *Conf) setDefaults() {
conf.MulticastRTCPPort = 8003
conf.ServerKey = "server.key"
conf.ServerCert = "server.crt"
conf.RTSPAuthMethods = RTSPAuthMethods{headers.AuthBasic}
conf.RTSPAuthMethods = RTSPAuthMethods{auth.ValidateMethodBasic}

// RTMP server
conf.RTMP = true
Expand Down Expand Up @@ -574,7 +574,7 @@ func (conf *Conf) Validate() error {
if conf.AuthMethods != nil {
conf.RTSPAuthMethods = *conf.AuthMethods
}
if contains(conf.RTSPAuthMethods, headers.AuthDigestMD5) {
if contains(conf.RTSPAuthMethods, auth.ValidateMethodDigestMD5) {
if conf.AuthMethod != AuthMethodInternal {
return fmt.Errorf("when RTSP digest is enabled, the only supported auth method is 'internal'")
}
Expand Down
10 changes: 5 additions & 5 deletions internal/conf/rtsp_auth_methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ import (
"sort"
"strings"

"github.com/bluenviron/gortsplib/v4/pkg/headers"
"github.com/bluenviron/gortsplib/v4/pkg/auth"
)

// RTSPAuthMethods is the rtspAuthMethods parameter.
type RTSPAuthMethods []headers.AuthMethod
type RTSPAuthMethods []auth.ValidateMethod

// MarshalJSON implements json.Marshaler.
func (d RTSPAuthMethods) MarshalJSON() ([]byte, error) {
out := make([]string, len(d))

for i, v := range d {
switch v {
case headers.AuthBasic:
case auth.ValidateMethodBasic:

Check warning on line 21 in internal/conf/rtsp_auth_methods.go

View check run for this annotation

Codecov / codecov/patch

internal/conf/rtsp_auth_methods.go#L21

Added line #L21 was not covered by tests
out[i] = "basic"

default:
Expand All @@ -43,10 +43,10 @@ func (d *RTSPAuthMethods) UnmarshalJSON(b []byte) error {
for _, v := range in {
switch v {
case "basic":
*d = append(*d, headers.AuthBasic)
*d = append(*d, auth.ValidateMethodBasic)

case "digest":
*d = append(*d, headers.AuthDigestMD5)
*d = append(*d, auth.ValidateMethodDigestMD5)

Check warning on line 49 in internal/conf/rtsp_auth_methods.go

View check run for this annotation

Codecov / codecov/patch

internal/conf/rtsp_auth_methods.go#L49

Added line #L49 was not covered by tests

default:
return fmt.Errorf("invalid authentication method: '%s'", v)
Expand Down
2 changes: 0 additions & 2 deletions internal/defs/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ type PathAccessRequest struct {
Proto auth.Protocol
ID *uuid.UUID
RTSPRequest *base.Request
RTSPBaseURL *base.URL
RTSPNonce string
}

Expand All @@ -70,7 +69,6 @@ func (r *PathAccessRequest) ToAuthRequest() *auth.Request {
ID: r.ID,
Query: r.Query,
RTSPRequest: r.RTSPRequest,
RTSPBaseURL: r.RTSPBaseURL,
RTSPNonce: r.RTSPNonce,
}
}
Expand Down
3 changes: 1 addition & 2 deletions internal/servers/rtsp/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/bluenviron/gortsplib/v4"
rtspauth "github.com/bluenviron/gortsplib/v4/pkg/auth"
"github.com/bluenviron/gortsplib/v4/pkg/base"
"github.com/bluenviron/gortsplib/v4/pkg/headers"
"github.com/google/uuid"

"github.com/bluenviron/mediamtx/internal/auth"
Expand All @@ -27,7 +26,7 @@ const (
type conn struct {
isTLS bool
rtspAddress string
authMethods []headers.AuthMethod
authMethods []rtspauth.ValidateMethod
readTimeout conf.StringDuration
runOnConnect string
runOnConnectRestart bool
Expand Down
4 changes: 2 additions & 2 deletions internal/servers/rtsp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"time"

"github.com/bluenviron/gortsplib/v4"
"github.com/bluenviron/gortsplib/v4/pkg/auth"
"github.com/bluenviron/gortsplib/v4/pkg/base"
"github.com/bluenviron/gortsplib/v4/pkg/headers"
"github.com/bluenviron/gortsplib/v4/pkg/liberrors"
"github.com/google/uuid"

Expand Down Expand Up @@ -59,7 +59,7 @@ type serverParent interface {
// Server is a RTSP server.
type Server struct {
Address string
AuthMethods []headers.AuthMethod
AuthMethods []auth.ValidateMethod
ReadTimeout conf.StringDuration
WriteTimeout conf.StringDuration
WriteQueueSize int
Expand Down
6 changes: 3 additions & 3 deletions internal/servers/rtsp/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import (
"time"

"github.com/bluenviron/gortsplib/v4"
"github.com/bluenviron/gortsplib/v4/pkg/auth"
"github.com/bluenviron/gortsplib/v4/pkg/base"
"github.com/bluenviron/gortsplib/v4/pkg/description"
"github.com/bluenviron/gortsplib/v4/pkg/format"
"github.com/bluenviron/gortsplib/v4/pkg/headers"
"github.com/bluenviron/mediamtx/internal/asyncwriter"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/defs"
Expand Down Expand Up @@ -93,7 +93,7 @@ func TestServerPublish(t *testing.T) {

s := &Server{
Address: "127.0.0.1:8557",
AuthMethods: []headers.AuthMethod{headers.AuthBasic},
AuthMethods: []auth.ValidateMethod{auth.ValidateMethodBasic},
ReadTimeout: conf.StringDuration(10 * time.Second),
WriteTimeout: conf.StringDuration(10 * time.Second),
WriteQueueSize: 512,
Expand Down Expand Up @@ -184,7 +184,7 @@ func TestServerRead(t *testing.T) {

s := &Server{
Address: "127.0.0.1:8557",
AuthMethods: []headers.AuthMethod{headers.AuthBasic},
AuthMethods: []auth.ValidateMethod{auth.ValidateMethodBasic},
ReadTimeout: conf.StringDuration(10 * time.Second),
WriteTimeout: conf.StringDuration(10 * time.Second),
WriteQueueSize: 512,
Expand Down
15 changes: 0 additions & 15 deletions internal/servers/rtsp/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ func (s *session) onAnnounce(c *conn, ctx *gortsplib.ServerHandlerOnAnnounceCtx)
Proto: auth.ProtocolRTSP,
ID: &c.uuid,
RTSPRequest: ctx.Request,
RTSPBaseURL: nil,
RTSPNonce: c.authNonce,
},
})
Expand Down Expand Up @@ -173,19 +172,6 @@ func (s *session) onSetup(c *conn, ctx *gortsplib.ServerHandlerOnSetupCtx,

switch s.rsession.State() {
case gortsplib.ServerSessionStateInitial, gortsplib.ServerSessionStatePrePlay: // play
baseURL := &base.URL{
Scheme: ctx.Request.URL.Scheme,
Host: ctx.Request.URL.Host,
Path: ctx.Path,
RawQuery: ctx.Query,
}

if ctx.Query != "" {
baseURL.RawQuery += "/"
} else {
baseURL.Path += "/"
}

if c.authNonce == "" {
var err error
c.authNonce, err = rtspauth.GenerateNonce()
Expand All @@ -205,7 +191,6 @@ func (s *session) onSetup(c *conn, ctx *gortsplib.ServerHandlerOnSetupCtx,
Proto: auth.ProtocolRTSP,
ID: &c.uuid,
RTSPRequest: ctx.Request,
RTSPBaseURL: baseURL,
RTSPNonce: c.authNonce,
},
})
Expand Down
4 changes: 2 additions & 2 deletions internal/staticsources/rtsp/source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func TestSource(t *testing.T) {
Handler: &testServer{
onDescribe: func(ctx *gortsplib.ServerHandlerOnDescribeCtx,
) (*base.Response, *gortsplib.ServerStream, error) {
err2 := auth.Validate(ctx.Request, "testuser", "testpass", nil, nil, "IPCAM", nonce)
err2 := auth.Validate(ctx.Request, "testuser", "testpass", nil, "IPCAM", nonce)
if err2 != nil {
return &base.Response{ //nolint:nilerr
StatusCode: base.StatusUnauthorized,
Expand Down Expand Up @@ -184,7 +184,7 @@ func TestRTSPSourceNoPassword(t *testing.T) {
s := gortsplib.Server{
Handler: &testServer{
onDescribe: func(ctx *gortsplib.ServerHandlerOnDescribeCtx) (*base.Response, *gortsplib.ServerStream, error) {
err2 := auth.Validate(ctx.Request, "testuser", "", nil, nil, "IPCAM", nonce)
err2 := auth.Validate(ctx.Request, "testuser", "", nil, "IPCAM", nonce)
if err2 != nil {
return &base.Response{ //nolint:nilerr
StatusCode: base.StatusUnauthorized,
Expand Down

0 comments on commit d21c559

Please sign in to comment.