mirror of
https://github.com/bluenviron/mediamtx.git
synced 2025-12-25 04:22:00 -08:00
add arguments --read-user --read-pass
This commit is contained in:
parent
dc52266a70
commit
5cbfaa4cd8
4 changed files with 114 additions and 28 deletions
|
|
@ -77,6 +77,8 @@ Flags:
|
|||
--write-timeout=5s timeout for write operations
|
||||
--publish-user="" optional username required to publish
|
||||
--publish-pass="" optional password required to publish
|
||||
--read-user="" optional username required to read
|
||||
--read-pass="" optional password required to read
|
||||
--pre-script="" optional script to run on client connect
|
||||
--post-script="" optional script to run on client disconnect
|
||||
```
|
||||
|
|
|
|||
6
main.go
6
main.go
|
|
@ -49,6 +49,8 @@ type args struct {
|
|||
writeTimeout time.Duration
|
||||
publishUser string
|
||||
publishPass string
|
||||
readUser string
|
||||
readPass string
|
||||
preScript string
|
||||
postScript string
|
||||
}
|
||||
|
|
@ -177,6 +179,8 @@ func main() {
|
|||
argWriteTimeout := kingpin.Flag("write-timeout", "timeout for write operations").Default("5s").Duration()
|
||||
argPublishUser := kingpin.Flag("publish-user", "optional username required to publish").Default("").String()
|
||||
argPublishPass := kingpin.Flag("publish-pass", "optional password required to publish").Default("").String()
|
||||
argReadUser := kingpin.Flag("read-user", "optional username required to read").Default("").String()
|
||||
argReadPass := kingpin.Flag("read-pass", "optional password required to read").Default("").String()
|
||||
argPreScript := kingpin.Flag("pre-script", "optional script to run on client connect").Default("").String()
|
||||
argPostScript := kingpin.Flag("post-script", "optional script to run on client disconnect").Default("").String()
|
||||
|
||||
|
|
@ -192,6 +196,8 @@ func main() {
|
|||
writeTimeout: *argWriteTimeout,
|
||||
publishUser: *argPublishUser,
|
||||
publishPass: *argPublishPass,
|
||||
readUser: *argReadUser,
|
||||
readPass: *argReadPass,
|
||||
preScript: *argPreScript,
|
||||
postScript: *argPostScript,
|
||||
})
|
||||
|
|
|
|||
45
main_test.go
45
main_test.go
|
|
@ -102,7 +102,7 @@ func TestProtocols(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAuthentication(t *testing.T) {
|
||||
func TestPublishAuth(t *testing.T) {
|
||||
p, err := newProgram(args{
|
||||
publishUser: "testuser",
|
||||
publishPass: "testpass",
|
||||
|
|
@ -144,3 +144,46 @@ func TestAuthentication(t *testing.T) {
|
|||
|
||||
require.Equal(t, "all right\n", string(cnt2.stdout.Bytes()))
|
||||
}
|
||||
|
||||
func TestReadAuth(t *testing.T) {
|
||||
p, err := newProgram(args{
|
||||
readUser: "testuser",
|
||||
readPass: "testpass",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer p.close()
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
cnt1, err := newContainer("ffmpeg", "source", []string{
|
||||
"-hide_banner",
|
||||
"-loglevel", "panic",
|
||||
"-re",
|
||||
"-stream_loop", "-1",
|
||||
"-i", "/emptyvideo.ts",
|
||||
"-c", "copy",
|
||||
"-f", "rtsp",
|
||||
"-rtsp_transport", "udp",
|
||||
"rtsp://localhost:8554/teststream",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer cnt1.close()
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
cnt2, err := newContainer("ffmpeg", "dest", []string{
|
||||
"-hide_banner",
|
||||
"-loglevel", "panic",
|
||||
"-rtsp_transport", "udp",
|
||||
"-i", "rtsp://testuser:testpass@localhost:8554/teststream",
|
||||
"-vframes", "1",
|
||||
"-f", "image2",
|
||||
"-y", "/dev/null",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer cnt2.close()
|
||||
|
||||
cnt2.wait()
|
||||
|
||||
require.Equal(t, "all right\n", string(cnt2.stdout.Bytes()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
|
@ -108,7 +109,8 @@ type serverClient struct {
|
|||
conn *gortsplib.ConnServer
|
||||
state clientState
|
||||
path string
|
||||
as *gortsplib.AuthServer
|
||||
publishAuth *gortsplib.AuthServer
|
||||
readAuth *gortsplib.AuthServer
|
||||
streamSdpText []byte // filled only if publisher
|
||||
streamSdpParsed *sdp.Message // filled only if publisher
|
||||
streamProtocol streamProtocol
|
||||
|
|
@ -240,6 +242,44 @@ func (c *serverClient) writeResError(req *gortsplib.Request, code gortsplib.Stat
|
|||
})
|
||||
}
|
||||
|
||||
var errAuthCritical = errors.New("auth critical")
|
||||
var errAuthNotCritical = errors.New("auth not critical")
|
||||
|
||||
func (c *serverClient) validateAuth(req *gortsplib.Request, user string, pass string, auth **gortsplib.AuthServer) error {
|
||||
if user == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
initialRequest := false
|
||||
if *auth == nil {
|
||||
initialRequest = true
|
||||
*auth = gortsplib.NewAuthServer(user, pass)
|
||||
}
|
||||
|
||||
err := (*auth).ValidateHeader(req.Header["Authorization"], req.Method, req.Url)
|
||||
if err != nil {
|
||||
if !initialRequest {
|
||||
c.log("ERR: Unauthorized: %s", err)
|
||||
}
|
||||
|
||||
c.conn.WriteResponse(&gortsplib.Response{
|
||||
StatusCode: gortsplib.StatusUnauthorized,
|
||||
Header: gortsplib.Header{
|
||||
"CSeq": []string{req.Header["CSeq"][0]},
|
||||
"WWW-Authenticate": (*auth).GenerateHeader(),
|
||||
},
|
||||
})
|
||||
|
||||
if !initialRequest {
|
||||
return errAuthCritical
|
||||
}
|
||||
|
||||
return errAuthNotCritical
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
|
||||
c.log(string(req.Method))
|
||||
|
||||
|
|
@ -293,6 +333,14 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
err := c.validateAuth(req, c.p.args.readUser, c.p.args.readPass, &c.readAuth)
|
||||
if err != nil {
|
||||
if err == errAuthCritical {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
sdp, err := func() ([]byte, error) {
|
||||
c.p.tcpl.mutex.RLock()
|
||||
defer c.p.tcpl.mutex.RUnlock()
|
||||
|
|
@ -326,33 +374,12 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if c.p.args.publishUser != "" {
|
||||
initialRequest := false
|
||||
if c.as == nil {
|
||||
initialRequest = true
|
||||
c.as = gortsplib.NewAuthServer(c.p.args.publishUser, c.p.args.publishPass)
|
||||
}
|
||||
|
||||
err := c.as.ValidateHeader(req.Header["Authorization"], gortsplib.ANNOUNCE, req.Url)
|
||||
if err != nil {
|
||||
if !initialRequest {
|
||||
c.log("ERR: Unauthorized: %s", err)
|
||||
}
|
||||
|
||||
c.conn.WriteResponse(&gortsplib.Response{
|
||||
StatusCode: gortsplib.StatusUnauthorized,
|
||||
Header: gortsplib.Header{
|
||||
"CSeq": []string{cseq[0]},
|
||||
"WWW-Authenticate": c.as.GenerateHeader(),
|
||||
},
|
||||
})
|
||||
|
||||
if !initialRequest {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
err := c.validateAuth(req, c.p.args.publishUser, c.p.args.publishPass, &c.publishAuth)
|
||||
if err != nil {
|
||||
if err == errAuthCritical {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
ct, ok := req.Header["Content-Type"]
|
||||
|
|
@ -420,6 +447,14 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
|
|||
switch c.state {
|
||||
// play
|
||||
case _CLIENT_STATE_STARTING, _CLIENT_STATE_PRE_PLAY:
|
||||
err := c.validateAuth(req, c.p.args.readUser, c.p.args.readPass, &c.readAuth)
|
||||
if err != nil {
|
||||
if err == errAuthCritical {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// play via UDP
|
||||
if func() bool {
|
||||
_, ok := th["RTP/AVP"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue