Files
gortsplib/pkg/auth/sender.go
2024-02-22 19:12:17 +01:00

106 lines
2.7 KiB
Go

package auth
import (
"fmt"
"github.com/bluenviron/gortsplib/v4/pkg/base"
"github.com/bluenviron/gortsplib/v4/pkg/headers"
)
func findAuthenticateHeader(auths []headers.Authenticate, method headers.AuthMethod) *headers.Authenticate {
for _, auth := range auths {
if auth.Method == method {
return &auth
}
}
return nil
}
func pickAuthenticateHeader(auths []headers.Authenticate) (*headers.Authenticate, error) {
if auth := findAuthenticateHeader(auths, headers.AuthDigestSHA256); auth != nil {
return auth, nil
}
if auth := findAuthenticateHeader(auths, headers.AuthDigestMD5); auth != nil {
return auth, nil
}
if auth := findAuthenticateHeader(auths, headers.AuthBasic); auth != nil {
return auth, nil
}
return nil, fmt.Errorf("no authentication methods available")
}
// Sender allows to send credentials.
type Sender struct {
user string
pass string
authenticateHeader *headers.Authenticate
}
// NewSender allocates a Sender.
// It requires a WWW-Authenticate header (provided by the server)
// and a set of credentials.
func NewSender(vals base.HeaderValue, user string, pass string) (*Sender, error) {
var auths []headers.Authenticate //nolint:prealloc
for _, v := range vals {
var auth headers.Authenticate
err := auth.Unmarshal(base.HeaderValue{v})
if err != nil {
continue // ignore unrecognized headers
}
auths = append(auths, auth)
}
auth, err := pickAuthenticateHeader(auths)
if err != nil {
return nil, err
}
return &Sender{
user: user,
pass: pass,
authenticateHeader: auth,
}, nil
}
// AddAuthorization adds the Authorization header to a Request.
func (se *Sender) AddAuthorization(req *base.Request) {
urStr := req.URL.CloneWithoutCredentials().String()
h := headers.Authorization{
Method: se.authenticateHeader.Method,
}
switch se.authenticateHeader.Method {
case headers.AuthBasic:
h.BasicUser = se.user
h.BasicPass = se.pass
case headers.AuthDigestMD5:
h.Username = se.user
h.Realm = se.authenticateHeader.Realm
h.Nonce = se.authenticateHeader.Nonce
h.URI = urStr
h.Response = md5Hex(md5Hex(se.user+":"+se.authenticateHeader.Realm+":"+se.pass) + ":" +
se.authenticateHeader.Nonce + ":" + md5Hex(string(req.Method)+":"+urStr))
default: // digest SHA-256
h.Username = se.user
h.Realm = se.authenticateHeader.Realm
h.Nonce = se.authenticateHeader.Nonce
h.URI = urStr
h.Response = sha256Hex(sha256Hex(se.user+":"+se.authenticateHeader.Realm+":"+se.pass) + ":" +
se.authenticateHeader.Nonce + ":" + sha256Hex(string(req.Method)+":"+urStr))
}
if req.Header == nil {
req.Header = make(base.Header)
}
req.Header["Authorization"] = h.Marshal()
}