feat(protocol): bind tunnel admission to device proof
Verify Protocol / verify (push) Canceled after 0s
Verify Protocol / module (push) Successful in 2m11s

This commit is contained in:
sechmachine
2026-07-29 10:32:08 +07:00
parent be709724ba
commit 4a2772c053
10 changed files with 138 additions and 14 deletions
+25 -1
View File
@@ -8,10 +8,11 @@ import (
"fmt"
"io"
"reflect"
"strings"
"time"
)
const SchemaSHA256 = "b8a69785112bb94d45f47c2250ca59d0bde47e3667b8ad89c9b0e2c4cfb25aec"
const SchemaSHA256 = "6b8631bf2b2aa12b14d0bc4d136af39a632e85b3237dc5614469ba09d93f5fca"
const ProtocolVersion = "1.0.0"
const CurrentWireVersion = "1"
const NMinus1WireVersion = "0"
@@ -326,6 +327,7 @@ type TunnelAdmissionRequest struct {
Grant string `json:"grant"`
ReconnectSequence int64 `json:"reconnect_sequence"`
ClientNonce string `json:"client_nonce"`
DeviceSignature string `json:"device_signature"`
Capabilities CapabilityProfile `json:"capabilities"`
}
@@ -3923,6 +3925,15 @@ func (v TunnelAdmissionRequest) Validate() error {
if len(v.ClientNonce) > 128 {
violations = append(violations, FieldViolation{Field: "client_nonce", Code: "max_length"})
}
if v.DeviceSignature == "" {
violations = append(violations, FieldViolation{Field: "device_signature", Code: "required"})
}
if len(v.DeviceSignature) < 86 && v.DeviceSignature != "" {
violations = append(violations, FieldViolation{Field: "device_signature", Code: "min_length"})
}
if len(v.DeviceSignature) > 86 {
violations = append(violations, FieldViolation{Field: "device_signature", Code: "max_length"})
}
if reflect.DeepEqual(v.Capabilities, CapabilityProfile{}) {
violations = append(violations, FieldViolation{Field: "capabilities", Code: "required"})
}
@@ -3953,6 +3964,9 @@ func DecodeTunnelAdmissionRequest(data []byte) (TunnelAdmissionRequest, error) {
if raw, ok := fields["client_nonce"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
return value, ValidationError{Violations: []FieldViolation{{Field: "client_nonce", Code: "required"}}}
}
if raw, ok := fields["device_signature"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
return value, ValidationError{Violations: []FieldViolation{{Field: "device_signature", Code: "required"}}}
}
if raw, ok := fields["gateway_id"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
return value, ValidationError{Violations: []FieldViolation{{Field: "gateway_id", Code: "required"}}}
}
@@ -4073,3 +4087,13 @@ func IntersectCapabilityProfiles(profiles ...CapabilityProfile) (CapabilityProfi
}
return selected, nil
}
func (v TunnelAdmissionRequest) DeviceAdmissionTranscript() []byte {
fields := []string{v.SessionID, v.GatewayID, v.Audience, v.Grant, fmt.Sprintf("%d", v.ReconnectSequence), v.ClientNonce, v.Capabilities.Transport, v.Capabilities.Framing, v.Capabilities.Media, v.Capabilities.Audio, v.Capabilities.SourceRateControl, v.Capabilities.ClientDecode}
var transcript strings.Builder
transcript.WriteString("versevdi/tunnel-admission/v1")
for _, field := range fields {
fmt.Fprintf(&transcript, "%d:%s", len(field), field)
}
return []byte(transcript.String())
}