Browse Source

add arguments --read-user --read-pass

pull/31/head v0.6.0
aler9 5 years ago
parent
commit
5cbfaa4cd8
  1. 2
      README.md
  2. 6
      main.go
  3. 45
      main_test.go
  4. 89
      server-client.go

2
README.md

@ -77,6 +77,8 @@ Flags: @@ -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

@ -49,6 +49,8 @@ type args struct { @@ -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() { @@ -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() { @@ -192,6 +196,8 @@ func main() {
writeTimeout: *argWriteTimeout,
publishUser: *argPublishUser,
publishPass: *argPublishPass,
readUser: *argReadUser,
readPass: *argReadPass,
preScript: *argPreScript,
postScript: *argPostScript,
})

45
main_test.go

@ -102,7 +102,7 @@ func TestProtocols(t *testing.T) { @@ -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) { @@ -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()))
}

89
server-client.go

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
package main
import (
"errors"
"fmt"
"io"
"log"
@ -108,7 +109,8 @@ type serverClient struct { @@ -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 @@ -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 { @@ -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 { @@ -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 { @@ -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…
Cancel
Save