mirror of
https://github.com/aler9/rtsp-simple-server
synced 2025-09-26 19:51:26 +08:00
@@ -260,7 +260,7 @@ func (a *API) middlewareAuth(ctx *gin.Context) {
|
|||||||
|
|
||||||
a.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), err.Wrapped)
|
a.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), err.Wrapped)
|
||||||
|
|
||||||
// wait some seconds to mitigate brute force attacks
|
// wait some seconds to delay brute force attacks
|
||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
ctx.AbortWithStatus(http.StatusUnauthorized)
|
ctx.AbortWithStatus(http.StatusUnauthorized)
|
||||||
|
@@ -164,7 +164,7 @@ func (m *Metrics) middlewareAuth(ctx *gin.Context) {
|
|||||||
|
|
||||||
m.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), err.Wrapped)
|
m.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), err.Wrapped)
|
||||||
|
|
||||||
// wait some seconds to mitigate brute force attacks
|
// wait some seconds to delay brute force attacks
|
||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
ctx.AbortWithStatus(http.StatusUnauthorized)
|
ctx.AbortWithStatus(http.StatusUnauthorized)
|
||||||
|
@@ -132,7 +132,7 @@ func (s *Server) doAuth(ctx *gin.Context, pathName string) bool {
|
|||||||
s.Log(logger.Info, "connection %v failed to authenticate: %v",
|
s.Log(logger.Info, "connection %v failed to authenticate: %v",
|
||||||
httpp.RemoteAddr(ctx), err.Wrapped)
|
httpp.RemoteAddr(ctx), err.Wrapped)
|
||||||
|
|
||||||
// wait some seconds to mitigate brute force attacks
|
// wait some seconds to delay brute force attacks
|
||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
ctx.Writer.WriteHeader(http.StatusUnauthorized)
|
ctx.Writer.WriteHeader(http.StatusUnauthorized)
|
||||||
|
@@ -110,7 +110,7 @@ func (pp *PPROF) middlewareAuth(ctx *gin.Context) {
|
|||||||
|
|
||||||
pp.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), err.Wrapped)
|
pp.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), err.Wrapped)
|
||||||
|
|
||||||
// wait some seconds to mitigate brute force attacks
|
// wait some seconds to delay brute force attacks
|
||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
ctx.AbortWithStatus(http.StatusUnauthorized)
|
ctx.AbortWithStatus(http.StatusUnauthorized)
|
||||||
|
@@ -164,7 +164,7 @@ func (s *httpServer) onRequest(ctx *gin.Context) {
|
|||||||
|
|
||||||
s.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), terr.Wrapped)
|
s.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), terr.Wrapped)
|
||||||
|
|
||||||
// wait some seconds to mitigate brute force attacks
|
// wait some seconds to delay brute force attacks
|
||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
ctx.Writer.WriteHeader(http.StatusUnauthorized)
|
ctx.Writer.WriteHeader(http.StatusUnauthorized)
|
||||||
|
@@ -13,9 +13,11 @@ import (
|
|||||||
"github.com/bluenviron/gohlslib/v2/pkg/codecs"
|
"github.com/bluenviron/gohlslib/v2/pkg/codecs"
|
||||||
"github.com/bluenviron/gortsplib/v5/pkg/description"
|
"github.com/bluenviron/gortsplib/v5/pkg/description"
|
||||||
"github.com/bluenviron/mediacommon/v2/pkg/codecs/mpeg4audio"
|
"github.com/bluenviron/mediacommon/v2/pkg/codecs/mpeg4audio"
|
||||||
|
"github.com/bluenviron/mediamtx/internal/auth"
|
||||||
"github.com/bluenviron/mediamtx/internal/conf"
|
"github.com/bluenviron/mediamtx/internal/conf"
|
||||||
"github.com/bluenviron/mediamtx/internal/defs"
|
"github.com/bluenviron/mediamtx/internal/defs"
|
||||||
"github.com/bluenviron/mediamtx/internal/externalcmd"
|
"github.com/bluenviron/mediamtx/internal/externalcmd"
|
||||||
|
"github.com/bluenviron/mediamtx/internal/logger"
|
||||||
"github.com/bluenviron/mediamtx/internal/stream"
|
"github.com/bluenviron/mediamtx/internal/stream"
|
||||||
"github.com/bluenviron/mediamtx/internal/test"
|
"github.com/bluenviron/mediamtx/internal/test"
|
||||||
"github.com/bluenviron/mediamtx/internal/unit"
|
"github.com/bluenviron/mediamtx/internal/unit"
|
||||||
@@ -500,3 +502,66 @@ func TestServerDynamicAlwaysRemux(t *testing.T) {
|
|||||||
|
|
||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAuthError(t *testing.T) {
|
||||||
|
n := 0
|
||||||
|
|
||||||
|
s := &Server{
|
||||||
|
Address: "127.0.0.1:8888",
|
||||||
|
Encryption: false,
|
||||||
|
ServerKey: "",
|
||||||
|
ServerCert: "",
|
||||||
|
AlwaysRemux: true,
|
||||||
|
Variant: conf.HLSVariant(gohlslib.MuxerVariantMPEGTS),
|
||||||
|
SegmentCount: 7,
|
||||||
|
SegmentDuration: conf.Duration(1 * time.Second),
|
||||||
|
PartDuration: conf.Duration(200 * time.Millisecond),
|
||||||
|
SegmentMaxSize: 50 * 1024 * 1024,
|
||||||
|
ReadTimeout: conf.Duration(10 * time.Second),
|
||||||
|
PathManager: &dummyPathManager{
|
||||||
|
findPathConfImpl: func(req defs.PathFindPathConfReq) (*conf.Path, error) {
|
||||||
|
if req.AccessRequest.Credentials.User == "" && req.AccessRequest.Credentials.Pass == "" {
|
||||||
|
return nil, &auth.Error{AskCredentials: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, &auth.Error{Wrapped: fmt.Errorf("auth error")}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Parent: test.Logger(func(l logger.Level, s string, i ...interface{}) {
|
||||||
|
if l == logger.Info {
|
||||||
|
if n == 1 {
|
||||||
|
require.Regexp(t, "failed to authenticate: auth error$", fmt.Sprintf(s, i...))
|
||||||
|
}
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
err := s.Initialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8888/stream/index.m3u8", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
res, err := http.DefaultClient.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
require.Equal(t, http.StatusUnauthorized, res.StatusCode)
|
||||||
|
require.Equal(t, `Basic realm="mediamtx"`, res.Header.Get("WWW-Authenticate"))
|
||||||
|
|
||||||
|
req, err = http.NewRequest(http.MethodGet, "http://myuser:mypass@127.0.0.1:8888/stream/index.m3u8", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
res, err = http.DefaultClient.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
require.Greater(t, time.Since(start), 2*time.Second)
|
||||||
|
|
||||||
|
require.Equal(t, http.StatusUnauthorized, res.StatusCode)
|
||||||
|
|
||||||
|
require.Equal(t, 2, n)
|
||||||
|
}
|
||||||
|
@@ -168,7 +168,7 @@ func (c *conn) runRead() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
var terr *auth.Error
|
var terr *auth.Error
|
||||||
if errors.As(err, &terr) {
|
if errors.As(err, &terr) {
|
||||||
// wait some seconds to mitigate brute force attacks
|
// wait some seconds to delay brute force attacks
|
||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
return terr
|
return terr
|
||||||
}
|
}
|
||||||
@@ -256,7 +256,7 @@ func (c *conn) runPublish() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
var terr *auth.Error
|
var terr *auth.Error
|
||||||
if errors.As(err, &terr) {
|
if errors.As(err, &terr) {
|
||||||
// wait some seconds to mitigate brute force attacks
|
// wait some seconds to delay brute force attacks
|
||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
return terr
|
return terr
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/bluenviron/gortsplib/v5"
|
"github.com/bluenviron/gortsplib/v5"
|
||||||
rtspauth "github.com/bluenviron/gortsplib/v5/pkg/auth"
|
rtspauth "github.com/bluenviron/gortsplib/v5/pkg/auth"
|
||||||
"github.com/bluenviron/gortsplib/v5/pkg/base"
|
"github.com/bluenviron/gortsplib/v5/pkg/base"
|
||||||
"github.com/bluenviron/gortsplib/v5/pkg/headers"
|
|
||||||
"github.com/bluenviron/gortsplib/v5/pkg/liberrors"
|
"github.com/bluenviron/gortsplib/v5/pkg/liberrors"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
|
||||||
@@ -37,12 +36,6 @@ func absoluteURL(req *base.Request, v string) string {
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func credentialsProvided(req *base.Request) bool {
|
|
||||||
var auth headers.Authorization
|
|
||||||
err := auth.Unmarshal(req.Header["Authorization"])
|
|
||||||
return err == nil && auth.Username != ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func tunnelLabel(t gortsplib.Tunnel) string {
|
func tunnelLabel(t gortsplib.Tunnel) string {
|
||||||
switch t {
|
switch t {
|
||||||
case gortsplib.TunnelHTTP:
|
case gortsplib.TunnelHTTP:
|
||||||
@@ -175,7 +168,7 @@ func (c *conn) onDescribe(ctx *gortsplib.ServerHandlerOnDescribeCtx,
|
|||||||
if res.Err != nil {
|
if res.Err != nil {
|
||||||
var terr *auth.Error
|
var terr *auth.Error
|
||||||
if errors.As(res.Err, &terr) {
|
if errors.As(res.Err, &terr) {
|
||||||
res, err2 := c.handleAuthError(ctx.Request)
|
res, err2 := c.handleAuthError(terr)
|
||||||
return res, nil, err2
|
return res, nil, err2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,17 +205,19 @@ func (c *conn) onDescribe(ctx *gortsplib.ServerHandlerOnDescribeCtx,
|
|||||||
}, stream, nil
|
}, stream, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *conn) handleAuthError(req *base.Request) (*base.Response, error) {
|
func (c *conn) handleAuthError(err *auth.Error) (*base.Response, error) {
|
||||||
if credentialsProvided(req) {
|
if err.AskCredentials {
|
||||||
// wait some seconds to mitigate brute force attacks
|
return &base.Response{
|
||||||
<-time.After(auth.PauseAfterError)
|
StatusCode: base.StatusUnauthorized,
|
||||||
|
}, liberrors.ErrServerAuth{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// let gortsplib decide whether connection should be terminated,
|
// wait some seconds to delay brute force attacks
|
||||||
// depending on whether credentials have been provided or not.
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusUnauthorized,
|
StatusCode: base.StatusUnauthorized,
|
||||||
}, liberrors.ErrServerAuth{}
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *conn) apiItem() *defs.APIRTSPConn {
|
func (c *conn) apiItem() *defs.APIRTSPConn {
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
package rtsp
|
package rtsp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -13,6 +15,7 @@ import (
|
|||||||
"github.com/bluenviron/mediamtx/internal/conf"
|
"github.com/bluenviron/mediamtx/internal/conf"
|
||||||
"github.com/bluenviron/mediamtx/internal/defs"
|
"github.com/bluenviron/mediamtx/internal/defs"
|
||||||
"github.com/bluenviron/mediamtx/internal/externalcmd"
|
"github.com/bluenviron/mediamtx/internal/externalcmd"
|
||||||
|
"github.com/bluenviron/mediamtx/internal/logger"
|
||||||
"github.com/bluenviron/mediamtx/internal/stream"
|
"github.com/bluenviron/mediamtx/internal/stream"
|
||||||
"github.com/bluenviron/mediamtx/internal/test"
|
"github.com/bluenviron/mediamtx/internal/test"
|
||||||
"github.com/bluenviron/mediamtx/internal/unit"
|
"github.com/bluenviron/mediamtx/internal/unit"
|
||||||
@@ -393,3 +396,54 @@ func TestServerRedirect(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAuthError(t *testing.T) {
|
||||||
|
pathManager := &test.PathManager{
|
||||||
|
DescribeImpl: func(req defs.PathDescribeReq) defs.PathDescribeRes {
|
||||||
|
if req.AccessRequest.Credentials.User == "" && req.AccessRequest.Credentials.Pass == "" {
|
||||||
|
return defs.PathDescribeRes{Err: &auth.Error{AskCredentials: true}}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defs.PathDescribeRes{Err: &auth.Error{Wrapped: fmt.Errorf("auth error")}}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
n := new(int64)
|
||||||
|
done := make(chan struct{})
|
||||||
|
|
||||||
|
s := &Server{
|
||||||
|
Address: "127.0.0.1:8557",
|
||||||
|
ReadTimeout: conf.Duration(10 * time.Second),
|
||||||
|
WriteTimeout: conf.Duration(10 * time.Second),
|
||||||
|
WriteQueueSize: 512,
|
||||||
|
PathManager: pathManager,
|
||||||
|
Parent: test.Logger(func(l logger.Level, s string, i ...interface{}) {
|
||||||
|
if l == logger.Info {
|
||||||
|
if atomic.AddInt64(n, 1) == 3 {
|
||||||
|
require.Regexp(t, "authentication failed: auth error$", fmt.Sprintf(s, i...))
|
||||||
|
close(done)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
err := s.Initialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
u, err := base.ParseURL("rtsp://myuser:mypass@127.0.0.1:8557/teststream?param=value")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
reader := gortsplib.Client{
|
||||||
|
Scheme: u.Scheme,
|
||||||
|
Host: u.Host,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = reader.Start()
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
|
_, _, err = reader.Describe(u)
|
||||||
|
require.EqualError(t, err, "bad status code: 401 (Unauthorized)")
|
||||||
|
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
@@ -179,7 +179,7 @@ func (s *session) onAnnounce(c *conn, ctx *gortsplib.ServerHandlerOnAnnounceCtx)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
var terr *auth.Error
|
var terr *auth.Error
|
||||||
if errors.As(err, &terr) {
|
if errors.As(err, &terr) {
|
||||||
return c.handleAuthError(ctx.Request)
|
return c.handleAuthError(terr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
@@ -242,7 +242,7 @@ func (s *session) onSetup(c *conn, ctx *gortsplib.ServerHandlerOnSetupCtx,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
var terr *auth.Error
|
var terr *auth.Error
|
||||||
if errors.As(err, &terr) {
|
if errors.As(err, &terr) {
|
||||||
res, err2 := c.handleAuthError(ctx.Request)
|
res, err2 := c.handleAuthError(terr)
|
||||||
return res, nil, err2
|
return res, nil, err2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -148,7 +148,7 @@ func (c *conn) runPublish(streamID *streamID) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
var terr *auth.Error
|
var terr *auth.Error
|
||||||
if errors.As(err, &terr) {
|
if errors.As(err, &terr) {
|
||||||
// wait some seconds to mitigate brute force attacks
|
// wait some seconds to delay brute force attacks
|
||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
c.connReq.Reject(srt.REJ_PEER)
|
c.connReq.Reject(srt.REJ_PEER)
|
||||||
return terr
|
return terr
|
||||||
@@ -272,7 +272,7 @@ func (c *conn) runRead(streamID *streamID) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
var terr *auth.Error
|
var terr *auth.Error
|
||||||
if errors.As(err, &terr) {
|
if errors.As(err, &terr) {
|
||||||
// wait some seconds to mitigate brute force attacks
|
// wait some seconds to delay brute force attacks
|
||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
c.connReq.Reject(srt.REJ_PEER)
|
c.connReq.Reject(srt.REJ_PEER)
|
||||||
return terr
|
return terr
|
||||||
|
@@ -141,7 +141,7 @@ func (s *httpServer) checkAuthOutsideSession(ctx *gin.Context, pathName string,
|
|||||||
|
|
||||||
s.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), terr.Wrapped)
|
s.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), terr.Wrapped)
|
||||||
|
|
||||||
// wait some seconds to mitigate brute force attacks
|
// wait some seconds to delay brute force attacks
|
||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
writeError(ctx, http.StatusUnauthorized, terr)
|
writeError(ctx, http.StatusUnauthorized, terr)
|
||||||
@@ -203,7 +203,7 @@ func (s *httpServer) onWHIPPost(ctx *gin.Context, pathName string, publish bool)
|
|||||||
|
|
||||||
s.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), terr.Wrapped)
|
s.Log(logger.Info, "connection %v failed to authenticate: %v", httpp.RemoteAddr(ctx), terr.Wrapped)
|
||||||
|
|
||||||
// wait some seconds to mitigate brute force attacks
|
// wait some seconds to delay brute force attacks
|
||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
writeError(ctx, http.StatusUnauthorized, terr)
|
writeError(ctx, http.StatusUnauthorized, terr)
|
||||||
|
@@ -3,6 +3,7 @@ package webrtc
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -12,9 +13,11 @@ import (
|
|||||||
|
|
||||||
"github.com/bluenviron/gortsplib/v5/pkg/description"
|
"github.com/bluenviron/gortsplib/v5/pkg/description"
|
||||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||||
|
"github.com/bluenviron/mediamtx/internal/auth"
|
||||||
"github.com/bluenviron/mediamtx/internal/conf"
|
"github.com/bluenviron/mediamtx/internal/conf"
|
||||||
"github.com/bluenviron/mediamtx/internal/defs"
|
"github.com/bluenviron/mediamtx/internal/defs"
|
||||||
"github.com/bluenviron/mediamtx/internal/externalcmd"
|
"github.com/bluenviron/mediamtx/internal/externalcmd"
|
||||||
|
"github.com/bluenviron/mediamtx/internal/logger"
|
||||||
"github.com/bluenviron/mediamtx/internal/protocols/webrtc"
|
"github.com/bluenviron/mediamtx/internal/protocols/webrtc"
|
||||||
"github.com/bluenviron/mediamtx/internal/protocols/whip"
|
"github.com/bluenviron/mediamtx/internal/protocols/whip"
|
||||||
"github.com/bluenviron/mediamtx/internal/stream"
|
"github.com/bluenviron/mediamtx/internal/stream"
|
||||||
@@ -63,9 +66,6 @@ func initializeTestServer(t *testing.T) *Server {
|
|||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
Address: "127.0.0.1:8886",
|
Address: "127.0.0.1:8886",
|
||||||
Encryption: false,
|
|
||||||
ServerKey: "",
|
|
||||||
ServerCert: "",
|
|
||||||
AllowOrigin: "*",
|
AllowOrigin: "*",
|
||||||
TrustedProxies: conf.IPNetworks{},
|
TrustedProxies: conf.IPNetworks{},
|
||||||
ReadTimeout: conf.Duration(10 * time.Second),
|
ReadTimeout: conf.Duration(10 * time.Second),
|
||||||
@@ -78,7 +78,6 @@ func initializeTestServer(t *testing.T) *Server {
|
|||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
HandshakeTimeout: conf.Duration(10 * time.Second),
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
||||||
ExternalCmdPool: nil,
|
|
||||||
PathManager: pm,
|
PathManager: pm,
|
||||||
Parent: test.NilLogger,
|
Parent: test.NilLogger,
|
||||||
}
|
}
|
||||||
@@ -148,10 +147,6 @@ func TestServerOptionsICEServer(t *testing.T) {
|
|||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
Address: "127.0.0.1:8886",
|
Address: "127.0.0.1:8886",
|
||||||
Encryption: false,
|
|
||||||
ServerKey: "",
|
|
||||||
ServerCert: "",
|
|
||||||
AllowOrigin: "",
|
|
||||||
TrustedProxies: conf.IPNetworks{},
|
TrustedProxies: conf.IPNetworks{},
|
||||||
ReadTimeout: conf.Duration(10 * time.Second),
|
ReadTimeout: conf.Duration(10 * time.Second),
|
||||||
LocalUDPAddress: "127.0.0.1:8887",
|
LocalUDPAddress: "127.0.0.1:8887",
|
||||||
@@ -167,7 +162,6 @@ func TestServerOptionsICEServer(t *testing.T) {
|
|||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
HandshakeTimeout: conf.Duration(10 * time.Second),
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
||||||
ExternalCmdPool: nil,
|
|
||||||
PathManager: pathManager,
|
PathManager: pathManager,
|
||||||
Parent: test.NilLogger,
|
Parent: test.NilLogger,
|
||||||
}
|
}
|
||||||
@@ -234,10 +228,6 @@ func TestServerPublish(t *testing.T) {
|
|||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
Address: "127.0.0.1:8886",
|
Address: "127.0.0.1:8886",
|
||||||
Encryption: false,
|
|
||||||
ServerKey: "",
|
|
||||||
ServerCert: "",
|
|
||||||
AllowOrigin: "",
|
|
||||||
TrustedProxies: conf.IPNetworks{},
|
TrustedProxies: conf.IPNetworks{},
|
||||||
ReadTimeout: conf.Duration(10 * time.Second),
|
ReadTimeout: conf.Duration(10 * time.Second),
|
||||||
LocalUDPAddress: "127.0.0.1:8887",
|
LocalUDPAddress: "127.0.0.1:8887",
|
||||||
@@ -249,7 +239,6 @@ func TestServerPublish(t *testing.T) {
|
|||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
HandshakeTimeout: conf.Duration(10 * time.Second),
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
||||||
ExternalCmdPool: nil,
|
|
||||||
PathManager: pathManager,
|
PathManager: pathManager,
|
||||||
Parent: test.NilLogger,
|
Parent: test.NilLogger,
|
||||||
}
|
}
|
||||||
@@ -523,11 +512,6 @@ func TestServerRead(t *testing.T) {
|
|||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
Address: "127.0.0.1:8886",
|
Address: "127.0.0.1:8886",
|
||||||
Encryption: false,
|
|
||||||
ServerKey: "",
|
|
||||||
ServerCert: "",
|
|
||||||
AllowOrigin: "",
|
|
||||||
TrustedProxies: conf.IPNetworks{},
|
|
||||||
ReadTimeout: conf.Duration(10 * time.Second),
|
ReadTimeout: conf.Duration(10 * time.Second),
|
||||||
LocalUDPAddress: "127.0.0.1:8887",
|
LocalUDPAddress: "127.0.0.1:8887",
|
||||||
LocalTCPAddress: "127.0.0.1:8887",
|
LocalTCPAddress: "127.0.0.1:8887",
|
||||||
@@ -538,7 +522,6 @@ func TestServerRead(t *testing.T) {
|
|||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
HandshakeTimeout: conf.Duration(10 * time.Second),
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
||||||
ExternalCmdPool: nil,
|
|
||||||
PathManager: pathManager,
|
PathManager: pathManager,
|
||||||
Parent: test.NilLogger,
|
Parent: test.NilLogger,
|
||||||
}
|
}
|
||||||
@@ -612,10 +595,6 @@ func TestServerReadNotFound(t *testing.T) {
|
|||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
Address: "127.0.0.1:8886",
|
Address: "127.0.0.1:8886",
|
||||||
Encryption: false,
|
|
||||||
ServerKey: "",
|
|
||||||
ServerCert: "",
|
|
||||||
AllowOrigin: "",
|
|
||||||
TrustedProxies: conf.IPNetworks{},
|
TrustedProxies: conf.IPNetworks{},
|
||||||
ReadTimeout: conf.Duration(10 * time.Second),
|
ReadTimeout: conf.Duration(10 * time.Second),
|
||||||
LocalUDPAddress: "127.0.0.1:8887",
|
LocalUDPAddress: "127.0.0.1:8887",
|
||||||
@@ -627,7 +606,6 @@ func TestServerReadNotFound(t *testing.T) {
|
|||||||
HandshakeTimeout: conf.Duration(10 * time.Second),
|
HandshakeTimeout: conf.Duration(10 * time.Second),
|
||||||
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
TrackGatherTimeout: conf.Duration(2 * time.Second),
|
||||||
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
STUNGatherTimeout: conf.Duration(5 * time.Second),
|
||||||
ExternalCmdPool: nil,
|
|
||||||
PathManager: pm,
|
PathManager: pm,
|
||||||
Parent: test.NilLogger,
|
Parent: test.NilLogger,
|
||||||
}
|
}
|
||||||
@@ -754,3 +732,57 @@ func TestICEServerClientOnly(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Empty(t, serverICEServers)
|
require.Empty(t, serverICEServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAuthError(t *testing.T) {
|
||||||
|
n := 0
|
||||||
|
|
||||||
|
s := &Server{
|
||||||
|
Address: "127.0.0.1:8886",
|
||||||
|
ReadTimeout: conf.Duration(10 * time.Second),
|
||||||
|
PathManager: &test.PathManager{
|
||||||
|
FindPathConfImpl: func(req defs.PathFindPathConfReq) (*conf.Path, error) {
|
||||||
|
if req.AccessRequest.Credentials.User == "" && req.AccessRequest.Credentials.Pass == "" {
|
||||||
|
return nil, &auth.Error{AskCredentials: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, &auth.Error{Wrapped: fmt.Errorf("auth error")}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Parent: test.Logger(func(l logger.Level, s string, i ...interface{}) {
|
||||||
|
if l == logger.Info {
|
||||||
|
if n == 1 {
|
||||||
|
require.Regexp(t, "failed to authenticate: auth error$", fmt.Sprintf(s, i...))
|
||||||
|
}
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
err := s.Initialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8886/stream/publish", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
res, err := http.DefaultClient.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
require.Equal(t, http.StatusUnauthorized, res.StatusCode)
|
||||||
|
require.Equal(t, `Basic realm="mediamtx"`, res.Header.Get("WWW-Authenticate"))
|
||||||
|
|
||||||
|
req, err = http.NewRequest(http.MethodGet, "http://myuser:mypass@127.0.0.1:8886/stream/publish", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
res, err = http.DefaultClient.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
require.Greater(t, time.Since(start), 2*time.Second)
|
||||||
|
|
||||||
|
require.Equal(t, http.StatusUnauthorized, res.StatusCode)
|
||||||
|
|
||||||
|
require.Equal(t, 2, n)
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user