mirror of
https://github.com/MengMengCode/VoCat.git
synced 2026-08-13 03:13:43 +08:00
158 lines
4.0 KiB
Go
158 lines
4.0 KiB
Go
package ims
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"vocat/internal/vowifi"
|
|
)
|
|
|
|
type recordingAKA struct {
|
|
result vowifi.AKAResult
|
|
err error
|
|
challenges []vowifi.AKAChallenge
|
|
}
|
|
|
|
func (aka *recordingAKA) CheckReady(context.Context, vowifi.SIMIdentity) (vowifi.AKAEvidence, error) {
|
|
return vowifi.AKAEvidence{Ready: true, Application: "usim"}, nil
|
|
}
|
|
|
|
func (aka *recordingAKA) Authenticate(
|
|
_ context.Context,
|
|
_ vowifi.SIMIdentity,
|
|
challenge vowifi.AKAChallenge,
|
|
) (vowifi.AKAResult, error) {
|
|
aka.challenges = append(aka.challenges, challenge)
|
|
return aka.result, aka.err
|
|
}
|
|
|
|
func TestDigestResponseRFC2617Vector(t *testing.T) {
|
|
got := digestResponse(
|
|
"Mufasa",
|
|
"[email protected]",
|
|
[]byte("Circle Of Life"),
|
|
"GET",
|
|
"/dir/index.html",
|
|
"dcd98b7102dd2f0e8b11d0f600bfb0c093",
|
|
"00000001",
|
|
"0a4f113b",
|
|
"auth",
|
|
)
|
|
const want = "6629fae49393a05397450978507c4ef1"
|
|
if got != want {
|
|
t.Fatalf("digestResponse() = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestAuthenticateAKAMapsNonceToTypedChallenge(t *testing.T) {
|
|
nonceBytes := make([]byte, 40)
|
|
for index := range nonceBytes {
|
|
nonceBytes[index] = byte(index)
|
|
}
|
|
aka := &recordingAKA{
|
|
result: vowifi.AKAResult{RES: []byte{0xde, 0xad, 0xbe, 0xef}},
|
|
}
|
|
material, err := authenticateAKA(
|
|
context.Background(),
|
|
aka,
|
|
vowifi.SIMIdentity{IMSI: "001010123456789"},
|
|
digestChallenge{Nonce: base64.StdEncoding.EncodeToString(nonceBytes)},
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("authenticateAKA() error = %v", err)
|
|
}
|
|
if !reflect.DeepEqual(material.response, []byte{0xde, 0xad, 0xbe, 0xef}) {
|
|
t.Fatalf("response = %x, want deadbeef", material.response)
|
|
}
|
|
if len(aka.challenges) != 1 {
|
|
t.Fatalf("challenge count = %d, want 1", len(aka.challenges))
|
|
}
|
|
var wantRAND, wantAUTN [16]byte
|
|
copy(wantRAND[:], nonceBytes[:16])
|
|
copy(wantAUTN[:], nonceBytes[16:32])
|
|
if !reflect.DeepEqual(aka.challenges[0].RAND, wantRAND) ||
|
|
!reflect.DeepEqual(aka.challenges[0].AUTN, wantAUTN) {
|
|
t.Fatalf("typed challenge = %#v", aka.challenges[0])
|
|
}
|
|
}
|
|
|
|
func TestAuthenticateAKAReturnsSynchronizationEvidence(t *testing.T) {
|
|
nonce := base64.StdEncoding.EncodeToString(make([]byte, 32))
|
|
auts := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
|
|
aka := &recordingAKA{
|
|
result: vowifi.AKAResult{
|
|
AUTS: auts,
|
|
SynchronizationFailure: true,
|
|
},
|
|
}
|
|
material, err := authenticateAKA(
|
|
context.Background(),
|
|
aka,
|
|
vowifi.SIMIdentity{},
|
|
digestChallenge{Nonce: nonce},
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("authenticateAKA() error = %v", err)
|
|
}
|
|
if !reflect.DeepEqual(material.auts, auts) || len(material.response) != 0 {
|
|
t.Fatalf("material = %#v", material)
|
|
}
|
|
}
|
|
|
|
func TestBuildDigestAuthorizationCarriesAUTSWithEmptyResponse(t *testing.T) {
|
|
authorization := buildDigestAuthorization(
|
|
digestChallenge{
|
|
Realm: "ims.example",
|
|
Nonce: "nonce",
|
|
Algorithm: "AKAv1-MD5",
|
|
QOP: "auth",
|
|
},
|
|
digestCredentials{
|
|
Username: "[email protected]",
|
|
AKAResponse: nil,
|
|
AUTS: "AAECAwQFBgcICQoLDA0=",
|
|
URI: "sip:ims.example",
|
|
Method: "REGISTER",
|
|
CNonce: "cnonce",
|
|
NC: 1,
|
|
},
|
|
)
|
|
directives, err := parseAuthDirectives(strings.TrimPrefix(authorization, "Digest "))
|
|
if err != nil {
|
|
t.Fatalf("parseAuthDirectives() error = %v", err)
|
|
}
|
|
if directives["auts"] != "AAECAwQFBgcICQoLDA0=" {
|
|
t.Fatalf("AUTS = %q", directives["auts"])
|
|
}
|
|
expected := digestResponse(
|
|
"[email protected]",
|
|
"ims.example",
|
|
nil,
|
|
"REGISTER",
|
|
"sip:ims.example",
|
|
"nonce",
|
|
"00000001",
|
|
"cnonce",
|
|
"auth",
|
|
)
|
|
if directives["response"] != expected {
|
|
t.Fatalf("response = %q, want %q", directives["response"], expected)
|
|
}
|
|
}
|
|
|
|
func TestParseDigestChallengeSelectsAuth(t *testing.T) {
|
|
challenge, err := parseDigestChallenge(
|
|
`Digest realm="ims.example", nonce="abc", algorithm=AKAv1-MD5, qop="auth-int, auth", opaque="x\"y"`,
|
|
false,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("parseDigestChallenge() error = %v", err)
|
|
}
|
|
if challenge.QOP != "auth" || challenge.Opaque != `x"y` {
|
|
t.Fatalf("challenge = %#v", challenge)
|
|
}
|
|
}
|