move auth utils into dedicated folder

This commit is contained in:
aler9
2020-10-04 18:15:24 +02:00
parent a465335210
commit 0db9c082e7
6 changed files with 27 additions and 24 deletions

View File

@@ -1,4 +1,4 @@
package gortsplib package auth
import ( import (
"encoding/base64" "encoding/base64"
@@ -10,9 +10,9 @@ import (
"github.com/aler9/gortsplib/headers" "github.com/aler9/gortsplib/headers"
) )
// authClient is an object that helps a client to send its credentials to a // Client is an object that helps a client to send its credentials to a
// server. // server.
type authClient struct { type Client struct {
user string user string
pass string pass string
method headers.AuthMethod method headers.AuthMethod
@@ -20,9 +20,9 @@ type authClient struct {
nonce string nonce string
} }
// newAuthClient allocates an authClient. // NewClient allocates an Client.
// header is the WWW-Authenticate header provided by the server. // header is the WWW-Authenticate header provided by the server.
func newAuthClient(v base.HeaderValue, user string, pass string) (*authClient, error) { func NewClient(v base.HeaderValue, user string, pass string) (*Client, error) {
// prefer digest // prefer digest
if headerAuthDigest := func() string { if headerAuthDigest := func() string {
for _, vi := range v { for _, vi := range v {
@@ -45,7 +45,7 @@ func newAuthClient(v base.HeaderValue, user string, pass string) (*authClient, e
return nil, fmt.Errorf("nonce not provided") return nil, fmt.Errorf("nonce not provided")
} }
return &authClient{ return &Client{
user: user, user: user,
pass: pass, pass: pass,
method: headers.AuthDigest, method: headers.AuthDigest,
@@ -71,7 +71,7 @@ func newAuthClient(v base.HeaderValue, user string, pass string) (*authClient, e
return nil, fmt.Errorf("realm not provided") return nil, fmt.Errorf("realm not provided")
} }
return &authClient{ return &Client{
user: user, user: user,
pass: pass, pass: pass,
method: headers.AuthBasic, method: headers.AuthBasic,
@@ -84,7 +84,7 @@ func newAuthClient(v base.HeaderValue, user string, pass string) (*authClient, e
// GenerateHeader generates an Authorization Header that allows to authenticate a request with // GenerateHeader generates an Authorization Header that allows to authenticate a request with
// the given method and url. // the given method and url.
func (ac *authClient) GenerateHeader(method base.Method, ur *url.URL) base.HeaderValue { func (ac *Client) GenerateHeader(method base.Method, ur *url.URL) base.HeaderValue {
switch ac.method { switch ac.method {
case headers.AuthBasic: case headers.AuthBasic:
response := base64.StdEncoding.EncodeToString([]byte(ac.user + ":" + ac.pass)) response := base64.StdEncoding.EncodeToString([]byte(ac.user + ":" + ac.pass))

2
auth/package.go Normal file
View File

@@ -0,0 +1,2 @@
// Package auth contains utilities to perform authentication.
package auth

View File

@@ -1,4 +1,4 @@
package gortsplib package auth
import ( import (
"net/url" "net/url"
@@ -31,10 +31,10 @@ var casesAuth = []struct {
func TestAuthMethods(t *testing.T) { func TestAuthMethods(t *testing.T) {
for _, c := range casesAuth { for _, c := range casesAuth {
t.Run(c.name, func(t *testing.T) { t.Run(c.name, func(t *testing.T) {
authServer := NewAuthServer("testuser", "testpass", c.methods) authServer := NewServer("testuser", "testpass", c.methods)
wwwAuthenticate := authServer.GenerateHeader() wwwAuthenticate := authServer.GenerateHeader()
ac, err := newAuthClient(wwwAuthenticate, "testuser", "testpass") ac, err := NewClient(wwwAuthenticate, "testuser", "testpass")
require.NoError(t, err) require.NoError(t, err)
authorization := ac.GenerateHeader(base.ANNOUNCE, authorization := ac.GenerateHeader(base.ANNOUNCE,
&url.URL{Scheme: "rtsp", Host: "myhost", Path: "mypath"}) &url.URL{Scheme: "rtsp", Host: "myhost", Path: "mypath"})
@@ -47,11 +47,11 @@ func TestAuthMethods(t *testing.T) {
} }
func TestAuthBasePath(t *testing.T) { func TestAuthBasePath(t *testing.T) {
authServer := NewAuthServer("testuser", "testpass", authServer := NewServer("testuser", "testpass",
[]headers.AuthMethod{headers.AuthBasic, headers.AuthDigest}) []headers.AuthMethod{headers.AuthBasic, headers.AuthDigest})
wwwAuthenticate := authServer.GenerateHeader() wwwAuthenticate := authServer.GenerateHeader()
ac, err := newAuthClient(wwwAuthenticate, "testuser", "testpass") ac, err := NewClient(wwwAuthenticate, "testuser", "testpass")
require.NoError(t, err) require.NoError(t, err)
authorization := ac.GenerateHeader(base.ANNOUNCE, authorization := ac.GenerateHeader(base.ANNOUNCE,
&url.URL{Scheme: "rtsp", Host: "myhost", Path: "mypath/"}) &url.URL{Scheme: "rtsp", Host: "myhost", Path: "mypath/"})

View File

@@ -1,4 +1,4 @@
package gortsplib package auth
import ( import (
"crypto/rand" "crypto/rand"
@@ -12,9 +12,9 @@ import (
"github.com/aler9/gortsplib/headers" "github.com/aler9/gortsplib/headers"
) )
// AuthServer is an object that helps a server to validate the credentials of // Server is an object that helps a server to validate the credentials of
// a client. // a client.
type AuthServer struct { type Server struct {
user string user string
pass string pass string
methods []headers.AuthMethod methods []headers.AuthMethod
@@ -22,9 +22,9 @@ type AuthServer struct {
nonce string nonce string
} }
// NewAuthServer allocates an AuthServer. // NewServer allocates an Server.
// If methods is nil, the Basic and Digest methods are used. // If methods is nil, the Basic and Digest methods are used.
func NewAuthServer(user string, pass string, methods []headers.AuthMethod) *AuthServer { func NewServer(user string, pass string, methods []headers.AuthMethod) *Server {
if methods == nil { if methods == nil {
methods = []headers.AuthMethod{headers.AuthBasic, headers.AuthDigest} methods = []headers.AuthMethod{headers.AuthBasic, headers.AuthDigest}
} }
@@ -33,7 +33,7 @@ func NewAuthServer(user string, pass string, methods []headers.AuthMethod) *Auth
rand.Read(nonceByts) rand.Read(nonceByts)
nonce := hex.EncodeToString(nonceByts) nonce := hex.EncodeToString(nonceByts)
return &AuthServer{ return &Server{
user: user, user: user,
pass: pass, pass: pass,
methods: methods, methods: methods,
@@ -43,7 +43,7 @@ func NewAuthServer(user string, pass string, methods []headers.AuthMethod) *Auth
} }
// GenerateHeader generates the WWW-Authenticate header needed by a client to log in. // GenerateHeader generates the WWW-Authenticate header needed by a client to log in.
func (as *AuthServer) GenerateHeader() base.HeaderValue { func (as *Server) GenerateHeader() base.HeaderValue {
var ret base.HeaderValue var ret base.HeaderValue
for _, m := range as.methods { for _, m := range as.methods {
switch m { switch m {
@@ -66,7 +66,7 @@ func (as *AuthServer) GenerateHeader() base.HeaderValue {
// ValidateHeader validates the Authorization header sent by a client after receiving the // ValidateHeader validates the Authorization header sent by a client after receiving the
// WWW-Authenticate header. // WWW-Authenticate header.
func (as *AuthServer) ValidateHeader(v base.HeaderValue, method base.Method, ur *url.URL) error { func (as *Server) ValidateHeader(v base.HeaderValue, method base.Method, ur *url.URL) error {
if len(v) == 0 { if len(v) == 0 {
return fmt.Errorf("authorization header not provided") return fmt.Errorf("authorization header not provided")
} }

View File

@@ -1,4 +1,4 @@
package gortsplib package auth
import ( import (
"crypto/md5" "crypto/md5"

View File

@@ -18,6 +18,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/aler9/gortsplib/auth"
"github.com/aler9/gortsplib/base" "github.com/aler9/gortsplib/base"
"github.com/aler9/gortsplib/headers" "github.com/aler9/gortsplib/headers"
"github.com/aler9/gortsplib/rtcpreceiver" "github.com/aler9/gortsplib/rtcpreceiver"
@@ -77,7 +78,7 @@ type ConnClient struct {
bw *bufio.Writer bw *bufio.Writer
session string session string
cseq int cseq int
auth *authClient auth *auth.Client
state connClientState state connClientState
streamUrl *url.URL streamUrl *url.URL
streamProtocol *StreamProtocol streamProtocol *StreamProtocol
@@ -308,7 +309,7 @@ func (c *ConnClient) Do(req *base.Request) (*base.Response, error) {
// setup authentication // setup authentication
if res.StatusCode == base.StatusUnauthorized && req.Url.User != nil && c.auth == nil { if res.StatusCode == base.StatusUnauthorized && req.Url.User != nil && c.auth == nil {
pass, _ := req.Url.User.Password() pass, _ := req.Url.User.Password()
auth, err := newAuthClient(res.Header["WWW-Authenticate"], req.Url.User.Username(), pass) auth, err := auth.NewClient(res.Header["WWW-Authenticate"], req.Url.User.Username(), pass)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to setup authentication: %s", err) return nil, fmt.Errorf("unable to setup authentication: %s", err)
} }