webrtc: send session ID to external auth server (#1981) (#2098)

This commit is contained in:
Alessandro Ros 2023-07-23 19:31:34 +02:00 committed by GitHub
parent af23609d47
commit 36298f8bc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 29 deletions

View File

@ -161,7 +161,7 @@ func (s *hlsHTTPServer) onRequest(ctx *gin.Context) {
return
}
s.Log(logger.Info, "authentication error: %v", terr.wrapped)
s.Log(logger.Info, "authentication failed: %v", terr.wrapped)
ctx.Writer.WriteHeader(http.StatusUnauthorized)
return
}

View File

@ -21,7 +21,8 @@ type testHTTPAuthenticator struct {
protocol string
action string
s *http.Server
s *http.Server
firstReceived bool
}
func newTestHTTPAuthenticator(t *testing.T, protocol string, action string) *testHTTPAuthenticator {
@ -75,7 +76,7 @@ func (ts *testHTTPAuthenticator) onAuth(ctx *gin.Context) {
in.Password != "testpass" ||
in.Path != "teststream" ||
in.Protocol != ts.protocol ||
// in.ID == "" ||
(ts.firstReceived && in.ID == "") ||
in.Action != ts.action ||
(in.Query != "user=testreader&pass=testpass&param=value" &&
in.Query != "user=testpublisher&pass=testpass&param=value" &&
@ -83,6 +84,8 @@ func (ts *testHTTPAuthenticator) onAuth(ctx *gin.Context) {
ctx.AbortWithStatus(http.StatusBadRequest)
return
}
ts.firstReceived = true
}
func httpPullFile(t *testing.T, hc *http.Client, u string) []byte {

View File

@ -30,7 +30,7 @@ type pathErrAuth struct {
// Error implements the error interface.
func (e pathErrAuth) Error() string {
return "authentication error"
return "authentication failed"
}
type pathErrNoOnePublishing struct {

View File

@ -293,35 +293,37 @@ func (s *webRTCHTTPServer) onRequest(ctx *gin.Context) {
ip := ctx.ClientIP()
_, port, _ := net.SplitHostPort(ctx.Request.RemoteAddr)
user, pass, hasCredentials := ctx.Request.BasicAuth()
res := s.pathManager.getConfForPath(pathGetConfForPathReq{
name: dir,
publish: publish,
credentials: authCredentials{
query: ctx.Request.URL.RawQuery,
ip: net.ParseIP(ip),
user: user,
pass: pass,
proto: authProtocolWebRTC,
},
})
if res.err != nil {
if terr, ok := res.err.(pathErrAuth); ok {
if !hasCredentials {
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
// if request doesn't belong to a session, check authentication here
if !isWHIPorWHEP || ctx.Request.Method == http.MethodOptions {
res := s.pathManager.getConfForPath(pathGetConfForPathReq{
name: dir,
publish: publish,
credentials: authCredentials{
query: ctx.Request.URL.RawQuery,
ip: net.ParseIP(ip),
user: user,
pass: pass,
proto: authProtocolWebRTC,
},
})
if res.err != nil {
if terr, ok := res.err.(pathErrAuth); ok {
if !hasCredentials {
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
ctx.Writer.WriteHeader(http.StatusUnauthorized)
return
}
s.Log(logger.Info, "authentication failed: %v", terr.wrapped)
ctx.Writer.WriteHeader(http.StatusUnauthorized)
return
}
s.Log(logger.Info, "authentication error: %v", terr.wrapped)
ctx.Writer.WriteHeader(http.StatusUnauthorized)
ctx.Writer.WriteHeader(http.StatusNotFound)
return
}
ctx.Writer.WriteHeader(http.StatusNotFound)
return
}
switch fname {
@ -357,6 +359,9 @@ func (s *webRTCHTTPServer) onRequest(ctx *gin.Context) {
res := s.parent.sessionNew(webRTCSessionNewReq{
pathName: dir,
remoteAddr: net.JoinHostPort(ip, port),
query: ctx.Request.URL.RawQuery,
user: user,
pass: pass,
offer: offer,
publish: (fname == "whip"),
})

View File

@ -97,6 +97,9 @@ type webRTCSessionNewRes struct {
type webRTCSessionNewReq struct {
pathName string
remoteAddr string
query string
user string
pass string
offer []byte
publish bool
res chan webRTCSessionNewRes

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding/hex"
"fmt"
"net"
"net/http"
"strings"
"sync"
@ -223,13 +224,25 @@ func (s *webRTCSession) runInner2() (int, error) {
}
func (s *webRTCSession) runPublish() (int, error) {
ip, _, _ := net.SplitHostPort(s.req.remoteAddr)
res := s.pathManager.publisherAdd(pathPublisherAddReq{
author: s,
pathName: s.req.pathName,
skipAuth: true,
credentials: authCredentials{
query: s.req.query,
ip: net.ParseIP(ip),
user: s.req.user,
pass: s.req.pass,
proto: authProtocolWebRTC,
id: &s.uuid,
},
})
if res.err != nil {
return http.StatusInternalServerError, res.err
if _, ok := res.err.(pathErrAuth); ok {
return http.StatusUnauthorized, res.err
}
return http.StatusBadRequest, res.err
}
defer res.path.publisherRemove(pathPublisherRemoveReq{author: s})
@ -334,16 +347,28 @@ func (s *webRTCSession) runPublish() (int, error) {
}
func (s *webRTCSession) runRead() (int, error) {
ip, _, _ := net.SplitHostPort(s.req.remoteAddr)
res := s.pathManager.readerAdd(pathReaderAddReq{
author: s,
pathName: s.req.pathName,
skipAuth: true,
credentials: authCredentials{
query: s.req.query,
ip: net.ParseIP(ip),
user: s.req.user,
pass: s.req.pass,
proto: authProtocolWebRTC,
id: &s.uuid,
},
})
if res.err != nil {
if _, ok := res.err.(pathErrAuth); ok {
return http.StatusUnauthorized, res.err
}
if strings.HasPrefix(res.err.Error(), "no one is publishing") {
return http.StatusNotFound, res.err
}
return http.StatusInternalServerError, res.err
return http.StatusBadRequest, res.err
}
defer res.path.readerRemove(pathReaderRemoveReq{author: s})