fix(gateway): close Phase 3C audit gaps

This commit is contained in:
sechmachine
2026-07-30 01:46:00 +07:00
parent 040ca73ce9
commit d3852d15f3
23 changed files with 1619 additions and 219 deletions
+58 -2
View File
@@ -55,6 +55,7 @@ func TestNativeApolloManagementUsesSessionScopedMTLS(t *testing.T) {
Version: "1", SessionID: "session-1", GatewayID: "gateway-1", ReconnectSequence: 0,
ExpiresAt: "2099-01-01T00:00:00Z", ProviderProfile: ProviderProfileApollo,
ProviderIdentity: "apollo-server#sha256:" + hex.EncodeToString(pinned[:]), PolicyVersionID: "policy-1", ApplicationID: "1", ClientID: "paired-client",
StreamPolicy: protocol.ProviderStreamPolicy{ResolutionWidth: 1920, ResolutionHeight: 1080, Fps: 60, Codec: "H264", BitrateKbps: 8000, AudioEnabled: true},
ManagementHost: host, ManagementPort: port, StreamHost: host, StreamPort: 47984,
ClientCertificatePem: certificatePEM(t, clientTLS.Certificates[0]),
ClientPrivateKeyPem: privateKeyPEM(t, clientTLS.Certificates[0]),
@@ -70,6 +71,32 @@ func TestNativeApolloManagementUsesSessionScopedMTLS(t *testing.T) {
}
}
func TestNativeApolloSetupRejectsUnsupportedStreamPolicyBeforeProviderReadiness(t *testing.T) {
work := protocol.ProviderSessionWork{
Version: "1", SessionID: "session-1", GatewayID: "gateway-1",
ExpiresAt: "2099-01-01T00:00:00Z", ProviderProfile: ProviderProfileApollo,
ProviderIdentity: "provider#sha256:00", PolicyVersionID: "policy-1",
ApplicationID: "1", ClientID: "client-1", ManagementHost: "127.0.0.1", ManagementPort: 1,
StreamHost: "127.0.0.1", StreamPort: 1, ClientCertificatePem: "invalid",
ClientPrivateKeyPem: "invalid", ServerCertificatePem: "invalid",
ClipboardPolicy: protocol.ClipboardPolicy{MaxTextBytes: 65536, MaxUpdatesPerMinute: 30},
}
for name, policy := range map[string]protocol.ProviderStreamPolicy{
"audio-disabled": {ResolutionWidth: 1920, ResolutionHeight: 1080, Fps: 60, Codec: "H264", BitrateKbps: 8000, AudioEnabled: false},
"av1": {ResolutionWidth: 3840, ResolutionHeight: 2160, Fps: 60, Codec: "AV1", BitrateKbps: 50000, AudioEnabled: true},
} {
t.Run(name, func(t *testing.T) {
work.StreamPolicy = policy
_, err := NewNativeApolloBackend().Setup(context.Background(), LaunchRequest{
SessionID: "session-1", ProviderProfile: ProviderProfileApollo, ProviderWork: work,
})
if !errors.Is(err, ErrProviderMalformed) {
t.Fatalf("Setup() error = %v, want ErrProviderMalformed before provider readiness", err)
}
})
}
}
func TestNativeApolloSetupRequiresModernEncryptedRTSPOrder(t *testing.T) {
serverTLS, clientTLS := testTLS(t)
streamListener, err := net.Listen("tcp", "127.0.0.1:0")
@@ -158,8 +185,9 @@ func TestNativeApolloSetupRequiresModernEncryptedRTSPOrder(t *testing.T) {
}
if method == "ANNOUNCE" {
for _, required := range []string{
"a=x-nv-video[0].clientViewportWd:1920", "a=x-nv-video[0].clientViewportHt:1080", "a=x-nv-video[0].maxFPS:60",
"a=x-nv-video[0].packetSize:1024", "a=x-nv-vqos[0].bw.maximumBitrateKbps:8000", "a=x-nv-audio.surround.numChannels:2",
"a=x-nv-video[0].clientViewportWd:2560", "a=x-nv-video[0].clientViewportHt:1440", "a=x-nv-video[0].maxFPS:120",
"a=x-nv-video[0].packetSize:1024", "a=x-nv-clientSupportHevc:1", "a=x-nv-vqos[0].bitStreamFormat:1",
"a=x-nv-vqos[0].bw.maximumBitrateKbps:32000", "a=x-ml-video.configuredBitrateKbps:40000", "a=x-nv-audio.surround.numChannels:2",
"a=x-nv-general.useReliableUdp:13", "a=x-ss-general.encryptionEnabled:7",
} {
if !strings.Contains(string(plaintext), required+"\r\n") {
@@ -255,6 +283,7 @@ func TestNativeApolloSetupRequiresModernEncryptedRTSPOrder(t *testing.T) {
Version: "1", SessionID: "session-1", GatewayID: "gateway-1", ReconnectSequence: 0,
ExpiresAt: "2099-01-01T00:00:00Z", ProviderProfile: ProviderProfileApollo,
ProviderIdentity: "apollo-server#sha256:" + hex.EncodeToString(pinned[:]), PolicyVersionID: "policy-1", ApplicationID: "42", ClientID: "paired-client",
StreamPolicy: protocol.ProviderStreamPolicy{ResolutionWidth: 2560, ResolutionHeight: 1440, Fps: 120, Codec: "HEVC", BitrateKbps: 40000, AudioEnabled: true},
ManagementHost: managementHost, ManagementPort: managementPort, StreamHost: streamHost, StreamPort: streamPort,
ClientCertificatePem: certificatePEM(t, clientTLS.Certificates[0]), ClientPrivateKeyPem: privateKeyPEM(t, clientTLS.Certificates[0]),
ServerCertificatePem: certificatePEM(t, tls.Certificate{Certificate: [][]byte{serverTLS.Certificates[0].Certificate[1]}}),
@@ -625,6 +654,33 @@ func TestNativeApolloSessionRelaysOnlyAuthenticatedEncodedUDPMedia(t *testing.T)
t.Fatal("encrypted FEC audio was not recovered")
}
}
for block := 0; block < apolloAudioMaximumBlocks+1; block++ {
sequence := uint16(100 + block*apolloAudioDataShards)
packet := sourceShapedEncryptedAudioPacketWithHeaders(t, key, keyID, sequence, uint32(sequence)*5, 1, []byte{byte(block)})
if _, err := audioServer.WriteToUDP(packet, audioClient.LocalAddr().(*net.UDPAddr)); err != nil {
t.Fatal(err)
}
}
for index, want := range [][]byte{{0xa0}, {0xa1}, {0xa2}, {0xa3}} {
sequence := uint16(124 + index)
packet := sourceShapedEncryptedAudioPacketWithHeaders(t, key, keyID, sequence, uint32(sequence)*5, 1, want)
if _, err := audioServer.WriteToUDP(packet, audioClient.LocalAddr().(*net.UDPAddr)); err != nil {
t.Fatal(err)
}
}
for _, want := range [][]byte{{0xa0}, {0xa1}, {0xa2}, {0xa3}} {
select {
case payload := <-session.Audio():
if string(payload) != string(want) {
t.Fatalf("post-loss audio relay = %x, want %x", payload, want)
}
case <-time.After(time.Second):
t.Fatal("sustained loss permanently stalled newer audio")
}
}
if drops := session.Telemetry().MediaDrops; drops < 2 {
t.Fatalf("stale FEC eviction drops = %d, want at least 2", drops)
}
terminateCtx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := session.Terminate(terminateCtx); err != nil {