diff --git a/challenge.go b/challenge.go index e8b98fb..d8c8309 100644 --- a/challenge.go +++ b/challenge.go @@ -35,7 +35,7 @@ func (c *Challenge) SupportsQOP(qop string) bool { // ParseChallenge parses the WWW-Authenticate header challenge func ParseChallenge(s string) (*Challenge, error) { - s, ok := strings.CutPrefix(s, Prefix) + s, ok := CutPrefix(s) if !ok { return nil, errors.New("digest: invalid challenge prefix") } diff --git a/challenge_test.go b/challenge_test.go index e1a5282..fc1aa28 100644 --- a/challenge_test.go +++ b/challenge_test.go @@ -12,6 +12,7 @@ import ( func TestChallenge(t *testing.T) { tests := []struct { input string + output string challenge *Challenge }{ { @@ -33,13 +34,25 @@ func TestChallenge(t *testing.T) { QOP: []string{"auth"}, }, }, + { + input: `DIGEST realm="DLI LPC92601002528", nonce="NZAeQHhoCNifFjFa"`, + output: `Digest realm="DLI LPC92601002528", nonce="NZAeQHhoCNifFjFa"`, + challenge: &Challenge{ + Realm: "DLI LPC92601002528", + Nonce: "NZAeQHhoCNifFjFa", + }, + }, } for i, tt := range tests { t.Run(strconv.Itoa(i), func(t *testing.T) { c, err := ParseChallenge(tt.input) assert.NilError(t, err) assert.DeepEqual(t, tt.challenge, c) - assert.DeepEqual(t, c.String(), tt.input) + output := tt.output + if output == "" { + output = tt.input + } + assert.DeepEqual(t, output, c.String()) }) } } diff --git a/credentials.go b/credentials.go index 56ff1df..dc86828 100644 --- a/credentials.go +++ b/credentials.go @@ -26,7 +26,7 @@ type Credentials struct { // ParseCredentials parses the Authorization header value into credentials func ParseCredentials(s string) (*Credentials, error) { - s, ok := strings.CutPrefix(s, Prefix) + s, ok := CutPrefix(s) if !ok { return nil, errors.New("digest: invalid credentials prefix") } diff --git a/digest.go b/digest.go index 1e6e082..2b87cb4 100644 --- a/digest.go +++ b/digest.go @@ -18,7 +18,18 @@ const Prefix = "Digest " // IsDigest returns true if the header value is a digest auth header func IsDigest(header string) bool { - return strings.HasPrefix(header, Prefix) + if len(header) < len(Prefix) { + return false + } + return strings.EqualFold(header[:len(Prefix)], Prefix) +} + +// CutPrefix removes the digest prefix from the header value +func CutPrefix(s string) (string, bool) { + if !IsDigest(s) { + return s, false + } + return s[len(Prefix):], true } // Options for creating a credentials diff --git a/digest_test.go b/digest_test.go index 73222ad..b2ba4bc 100644 --- a/digest_test.go +++ b/digest_test.go @@ -70,6 +70,30 @@ func TestDigestMD5(t *testing.T) { Nc: 1, }, }, + { + Options{ + Method: "REGISTER", + URI: "sip:182.82.132.122", + Username: "the-user", + Password: "********", + Cnonce: "104adc6bd71f49678798ee646edcaa9a", + }, + &Challenge{ + Realm: "SipPeer", + Nonce: "970a1b42-d8a7-4fce-91a1-4767e9ed561b", + QOP: []string{"auth"}, + }, + &Credentials{ + Username: "the-user", + Realm: "SipPeer", + Nonce: "970a1b42-d8a7-4fce-91a1-4767e9ed561b", + URI: "sip:182.82.132.122", + Response: "6cf0981e056709d40c8acc40c87e73c6", + Cnonce: "104adc6bd71f49678798ee646edcaa9a", + QOP: "auth", + Nc: 1, + }, + }, } for _, tt := range tests { t.Run("", func(t *testing.T) {