Protocol: split client session authority
This commit is contained in:
@@ -3,6 +3,7 @@ package protocol_test
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -362,6 +363,81 @@ func TestSessionAuthorityRejectsProviderRoute(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientSessionAuthorityIsStrictAndProviderFree(t *testing.T) {
|
||||
authority := protocol.ClientSessionAuthority{
|
||||
Version: "1", SessionID: "session-1", GatewayID: "gateway-1", Audience: "versevdi-gateway",
|
||||
ReconnectSequence: 2, ExpiresAt: "2099-01-01T00:00:00Z", Capabilities: protocol.CapabilityProfile{
|
||||
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded", Audio: "encoded",
|
||||
SourceRateControl: "server", ClientDecode: []string{"h264-opus"},
|
||||
},
|
||||
}
|
||||
encoded, err := protocol.EncodeClientSessionAuthority(authority)
|
||||
if err != nil {
|
||||
t.Fatalf("EncodeClientSessionAuthority() error = %v", err)
|
||||
}
|
||||
var fields map[string]json.RawMessage
|
||||
if err := json.Unmarshal(encoded, &fields); err != nil {
|
||||
t.Fatalf("encoded client authority is not JSON: %v", err)
|
||||
}
|
||||
wantFields := map[string]bool{
|
||||
"version": true, "session_id": true, "gateway_id": true, "audience": true,
|
||||
"reconnect_sequence": true, "expires_at": true, "capabilities": true,
|
||||
}
|
||||
if len(fields) != len(wantFields) {
|
||||
t.Fatalf("encoded client authority fields = %v; want exactly %v", fields, wantFields)
|
||||
}
|
||||
for field := range fields {
|
||||
if !wantFields[field] {
|
||||
t.Fatalf("encoded client authority contains forbidden field %q", field)
|
||||
}
|
||||
}
|
||||
if bytes.Contains(encoded, []byte("provider_")) {
|
||||
t.Fatalf("encoded client authority disclosed provider data: %s", encoded)
|
||||
}
|
||||
decoded, err := protocol.DecodeClientSessionAuthority(encoded)
|
||||
if err != nil || !reflect.DeepEqual(decoded, authority) {
|
||||
t.Fatalf("DecodeClientSessionAuthority() = %+v, %v; want %+v", decoded, err, authority)
|
||||
}
|
||||
|
||||
for _, field := range []string{"version", "session_id", "gateway_id", "audience", "reconnect_sequence", "expires_at", "capabilities"} {
|
||||
missing := make(map[string]json.RawMessage, len(fields)-1)
|
||||
for key, value := range fields {
|
||||
if key != field {
|
||||
missing[key] = value
|
||||
}
|
||||
}
|
||||
payload, err := json.Marshal(missing)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := protocol.DecodeClientSessionAuthority(payload); err == nil {
|
||||
t.Fatalf("DecodeClientSessionAuthority accepted missing %q", field)
|
||||
}
|
||||
}
|
||||
|
||||
for name, value := range map[string]string{
|
||||
"provider_profile": `"apollo"`,
|
||||
"provider_identity": `"provider-1"`,
|
||||
"provider_url": `"https://provider.invalid"`,
|
||||
"management_host": `"provider.invalid"`,
|
||||
"unknown": `true`,
|
||||
} {
|
||||
payload := append(append([]byte(nil), encoded[:len(encoded)-1]...), []byte(`,"`+name+`":`+value+`}`)...)
|
||||
if _, err := protocol.DecodeClientSessionAuthority(payload); err == nil {
|
||||
t.Fatalf("DecodeClientSessionAuthority accepted injected %q", name)
|
||||
}
|
||||
}
|
||||
for _, expiresAt := range []string{"not-a-time", "2099-01-01T00:00:00+00:00", "2099-01-01T00:00:00.100Z"} {
|
||||
payload := bytes.Replace(encoded, []byte("2099-01-01T00:00:00Z"), []byte(expiresAt), 1)
|
||||
if _, err := protocol.DecodeClientSessionAuthority(payload); err == nil {
|
||||
t.Fatalf("DecodeClientSessionAuthority accepted expires_at %q", expiresAt)
|
||||
}
|
||||
}
|
||||
if _, err := protocol.DecodeClientSessionAuthority(append(encoded, []byte(" {}")...)); err == nil {
|
||||
t.Fatal("DecodeClientSessionAuthority accepted trailing JSON")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProviderSessionWorkIsStrictAndSessionBound(t *testing.T) {
|
||||
valid := `{"version":"1","session_id":"session-1","gateway_id":"gateway-1","reconnect_sequence":0,"expires_at":"2099-01-01T00:00:00Z","provider_profile":"apollo","provider_identity":"provider-1","policy_version_id":"policy-1","stream_policy":{"resolution_width":2560,"resolution_height":1440,"fps":120,"codec":"HEVC","bitrate_kbps":40000,"audio_enabled":true},"application_id":"42","client_id":"paired-client-1","management_host":"apollo.test","management_port":47990,"stream_host":"apollo.test","stream_port":47984,"client_certificate_pem":"certificate","client_private_key_pem":"private-key","server_certificate_pem":"server-certificate","clipboard_policy":{"client_to_provider_enabled":false,"provider_to_client_enabled":false,"max_text_bytes":65536,"max_updates_per_minute":30},"provider_application_termination_allowed":false}`
|
||||
if _, err := protocol.DecodeProviderSessionWork([]byte(valid)); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user