| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- 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.password, []byte{0xde, 0xad, 0xbe, 0xef}) {
- t.Fatalf("password = %x, want deadbeef", material.password)
- }
- 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.password) != 0 {
- t.Fatalf("material = %#v", material)
- }
- }
- func TestBuildDigestAuthorizationCarriesAUTSWithEmptyPassword(t *testing.T) {
- authorization := buildDigestAuthorization(
- digestChallenge{
- Realm: "ims.example",
- Nonce: "nonce",
- Algorithm: "AKAv1-MD5",
- QOP: "auth",
- },
- digestCredentials{
- Username: "[email protected]",
- Password: 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)
- }
- }
|