require matching live tcpdump before real call

This commit is contained in:
2026-10-04 21:39:19 +08:00
parent 08f827ecdf
commit e0bd987946
2 changed files with 39 additions and 2 deletions
+19
View File
@@ -201,9 +201,28 @@ func verifyCallEvidence(root, id, trunk, target string) error {
if end == -1 || len(state) <= end+2 || state[end+2] == 'Z' || state[end+2] == 'X' {
return errors.New("real call capture process has ended")
}
// /proc/<pid>/exe is not readable by the unprivileged Agent when
// the host evidence script starts tcpdump as root.
comm, err := os.ReadFile(filepath.Join("/proc", fields[0], "comm"))
if err != nil || strings.TrimSpace(string(comm)) != "tcpdump" {
return errors.New("real call capture process is not tcpdump")
}
args, err := os.ReadFile(filepath.Join("/proc", fields[0], "cmdline"))
if err != nil || !capturesCall(strings.Split(string(args), "\x00"), id) {
return errors.New("real call capture process does not record this call")
}
return nil
}
func capturesCall(args []string, id string) bool {
for i := 0; i+1 < len(args); i++ {
if args[i] == "-w" && filepath.IsAbs(args[i+1]) && filepath.Base(args[i+1]) == "capture.pcap" && filepath.Base(filepath.Dir(args[i+1])) == id {
return true
}
}
return false
}
func (r *ApprovedRecordedRealCall) Run(ctx context.Context, approved ApprovedExecution) error {
if ctx == nil {
return errors.New("real call requires a context")
+20 -2
View File
@@ -33,8 +33,8 @@ func TestRealCallRequiresLiveCaptureBoundToSignedIdentity(t *testing.T) {
if err := os.WriteFile(marker, []byte(fmt.Sprintf("%d\t%s\t%s\n", os.Getpid(), trunk, target)), 0640); err != nil {
t.Fatal(err)
}
if err := verifyCallEvidence(root, id, trunk, target); err != nil {
t.Fatal(err)
if err := verifyCallEvidence(root, id, trunk, target); err == nil {
t.Fatal("a live process other than tcpdump must not arm real dialing")
}
if err := verifyCallEvidence(root, id, trunk, "15830461047"); err == nil {
t.Fatal("capture bound to a different callee cannot authorize a real call")
@@ -50,6 +50,24 @@ func TestRealCallRequiresLiveCaptureBoundToSignedIdentity(t *testing.T) {
}
}
func TestCaptureProcessMustWriteThisCall(t *testing.T) {
id := "event-1"
args := []string{"/usr/bin/tcpdump", "-i", "any", "-nn", "-s0", "-U", "-w", "/var/lib/sip-go-agent/evidence/event-1/capture.pcap", "udp port 5060 or (udp portrange 10000-20000)"}
if !capturesCall(args, id) {
t.Fatal("the host script's tcpdump command must be recognized")
}
for _, bad := range [][]string{
{"/usr/bin/tcpdump", "-w", "/var/lib/sip-go-agent/evidence/other/capture.pcap"},
{"/usr/bin/tcpdump", "-w", "/var/lib/sip-go-agent/evidence/event-1/other.pcap"},
{"/usr/bin/tcpdump", "-w", "event-1/capture.pcap"},
{"/usr/bin/tcpdump", "/var/lib/sip-go-agent/evidence/event-1/capture.pcap"},
} {
if capturesCall(bad, id) {
t.Fatalf("unrelated capture command accepted: %q", bad)
}
}
}
func TestApprovedRecordedRealCallReportsOnlyEndedObservedCall(t *testing.T) {
fixture, stub, puts, _, approved := recordedMockFixture(t, nil, time.Second)
approved.CallerID, approved.DialedCallee, approved.RingTimeout = "BD93205882", "7089"+approved.Callee, time.Second