@@ -2,19 +2,34 @@ package auth
2
2
3
3
import (
4
4
"fmt"
5
- "strings"
6
5
7
6
"github.com/bluenviron/gortsplib/v4/pkg/base"
8
7
"github.com/bluenviron/gortsplib/v4/pkg/headers"
9
8
)
10
9
11
- func findHeader ( v base. HeaderValue , prefix string ) string {
12
- for _ , vi := range v {
13
- if strings . HasPrefix ( vi , prefix ) {
14
- return vi
10
+ func findAuthenticateHeader ( auths []headers. Authenticate , method headers. AuthMethod ) * headers. Authenticate {
11
+ for _ , auth := range auths {
12
+ if auth . Method == method {
13
+ return & auth
15
14
}
16
15
}
17
- return ""
16
+ return nil
17
+ }
18
+
19
+ func pickAuthenticateHeader (auths []headers.Authenticate ) (* headers.Authenticate , error ) {
20
+ if auth := findAuthenticateHeader (auths , headers .AuthDigestSHA256 ); auth != nil {
21
+ return auth , nil
22
+ }
23
+
24
+ if auth := findAuthenticateHeader (auths , headers .AuthDigestMD5 ); auth != nil {
25
+ return auth , nil
26
+ }
27
+
28
+ if auth := findAuthenticateHeader (auths , headers .AuthBasic ); auth != nil {
29
+ return auth , nil
30
+ }
31
+
32
+ return nil , fmt .Errorf ("no authentication methods available" )
18
33
}
19
34
20
35
// Sender allows to send credentials.
@@ -27,37 +42,29 @@ type Sender struct {
27
42
// NewSender allocates a Sender.
28
43
// It requires a WWW-Authenticate header (provided by the server)
29
44
// and a set of credentials.
30
- func NewSender (v base.HeaderValue , user string , pass string ) (* Sender , error ) {
31
- // prefer digest
32
- if v0 := findHeader (v , "Digest" ); v0 != "" {
45
+ func NewSender (vals base.HeaderValue , user string , pass string ) (* Sender , error ) {
46
+ var auths []headers.Authenticate //nolint:prealloc
47
+
48
+ for _ , v := range vals {
33
49
var auth headers.Authenticate
34
- err := auth .Unmarshal (base.HeaderValue {v0 })
50
+ err := auth .Unmarshal (base.HeaderValue {v })
35
51
if err != nil {
36
- return nil , err
52
+ continue // ignore unrecognized headers
37
53
}
38
54
39
- return & Sender {
40
- user : user ,
41
- pass : pass ,
42
- authenticateHeader : & auth ,
43
- }, nil
55
+ auths = append (auths , auth )
44
56
}
45
57
46
- if v0 := findHeader (v , "Basic" ); v0 != "" {
47
- var auth headers.Authenticate
48
- err := auth .Unmarshal (base.HeaderValue {v0 })
49
- if err != nil {
50
- return nil , err
51
- }
52
-
53
- return & Sender {
54
- user : user ,
55
- pass : pass ,
56
- authenticateHeader : & auth ,
57
- }, nil
58
+ auth , err := pickAuthenticateHeader (auths )
59
+ if err != nil {
60
+ return nil , err
58
61
}
59
62
60
- return nil , fmt .Errorf ("no authentication methods available" )
63
+ return & Sender {
64
+ user : user ,
65
+ pass : pass ,
66
+ authenticateHeader : auth ,
67
+ }, nil
61
68
}
62
69
63
70
// AddAuthorization adds the Authorization header to a Request.
@@ -68,16 +75,26 @@ func (se *Sender) AddAuthorization(req *base.Request) {
68
75
Method : se .authenticateHeader .Method ,
69
76
}
70
77
71
- if se .authenticateHeader .Method == headers .AuthBasic {
78
+ switch se .authenticateHeader .Method {
79
+ case headers .AuthBasic :
72
80
h .BasicUser = se .user
73
81
h .BasicPass = se .pass
74
- } else { // digest
82
+
83
+ case headers .AuthDigestMD5 :
75
84
h .Username = se .user
76
85
h .Realm = se .authenticateHeader .Realm
77
86
h .Nonce = se .authenticateHeader .Nonce
78
87
h .URI = urStr
79
88
h .Response = md5Hex (md5Hex (se .user + ":" + se .authenticateHeader .Realm + ":" + se .pass ) + ":" +
80
89
se .authenticateHeader .Nonce + ":" + md5Hex (string (req .Method )+ ":" + urStr ))
90
+
91
+ default : // digest SHA-256
92
+ h .Username = se .user
93
+ h .Realm = se .authenticateHeader .Realm
94
+ h .Nonce = se .authenticateHeader .Nonce
95
+ h .URI = urStr
96
+ h .Response = sha256Hex (sha256Hex (se .user + ":" + se .authenticateHeader .Realm + ":" + se .pass ) + ":" +
97
+ se .authenticateHeader .Nonce + ":" + sha256Hex (string (req .Method )+ ":" + urStr ))
81
98
}
82
99
83
100
if req .Header == nil {
0 commit comments