support hashed credentials

This commit is contained in:
aler9
2020-12-31 19:27:41 +01:00
parent b2f56c9814
commit 9bd587e576
4 changed files with 178 additions and 50 deletions

View File

@@ -11,13 +11,15 @@ import (
"github.com/aler9/gortsplib/pkg/headers"
)
// Validator allows a server to validate some credentials sent by a client.
// Validator allows to validate some credentials generated by a Sender.
type Validator struct {
user string
pass string
methods []headers.AuthMethod
realm string
nonce string
user string
userHashed bool
pass string
passHashed bool
methods []headers.AuthMethod
realm string
nonce string
}
// NewValidator allocates a Validator.
@@ -27,16 +29,39 @@ func NewValidator(user string, pass string, methods []headers.AuthMethod) *Valid
methods = []headers.AuthMethod{headers.AuthBasic, headers.AuthDigest}
}
userHashed := false
if strings.HasPrefix(user, "plain:") {
user = strings.TrimPrefix(user, "plain:")
} else if strings.HasPrefix(user, "sha256:") {
user = strings.TrimPrefix(user, "sha256:")
userHashed = true
}
passHashed := false
if strings.HasPrefix(pass, "plain:") {
pass = strings.TrimPrefix(pass, "plain:")
} else if strings.HasPrefix(pass, "sha256:") {
pass = strings.TrimPrefix(pass, "sha256:")
passHashed = true
}
// if credentials are hashed, only basic auth is supported
if userHashed || passHashed {
methods = []headers.AuthMethod{headers.AuthBasic}
}
nonceByts := make([]byte, 16)
rand.Read(nonceByts)
nonce := hex.EncodeToString(nonceByts)
return &Validator{
user: user,
pass: pass,
methods: methods,
realm: "IPCAM",
nonce: nonce,
user: user,
userHashed: userHashed,
pass: pass,
passHashed: passHashed,
methods: methods,
realm: "IPCAM",
nonce: nonce,
}
}
@@ -78,11 +103,35 @@ func (va *Validator) ValidateHeader(v base.HeaderValue, method base.Method, ur *
if strings.HasPrefix(v0, "Basic ") {
inResponse := v0[len("Basic "):]
response := base64.StdEncoding.EncodeToString([]byte(va.user + ":" + va.pass))
if inResponse != response {
tmp, err := base64.StdEncoding.DecodeString(inResponse)
if err != nil {
return fmt.Errorf("wrong response")
}
tmp2 := strings.Split(string(tmp), ":")
if len(tmp2) != 2 {
return fmt.Errorf("wrong response")
}
user, pass := tmp2[0], tmp2[1]
if !va.userHashed {
if user != va.user {
return fmt.Errorf("wrong response")
}
} else {
if sha256Base64(user) != va.user {
return fmt.Errorf("wrong response")
}
}
if !va.passHashed {
if pass != va.pass {
return fmt.Errorf("wrong response")
}
} else {
if sha256Base64(pass) != va.pass {
return fmt.Errorf("wrong response")
}
}
} else if strings.HasPrefix(v0, "Digest ") {
auth, err := headers.ReadAuth(base.HeaderValue{v0})