// SPDX-License-Identifier: AGPL-3.0-only package transport import ( "bufio" "bytes" "crypto/sha256" "encoding/hex" "strings" "testing" ) func validFrame(t *testing.T, artifact string) ([]byte, Header) { t.Helper() hash := sha256.Sum256([]byte(artifact)) digest := hex.EncodeToString(hash[:]) header := Header{Protocol: Protocol, Service: "example-site", ArtifactName: "example.tar.gz", Size: int64(len(artifact)), SHA256: digest, ApprovedSHA256: digest, Activate: true} prefix, err := Prefix(header) if err != nil { t.Fatal(err) } return append(prefix, artifact...), header } func TestProtocolRoundTrip(t *testing.T) { frame, expected := validFrame(t, "artifact") reader := bufio.NewReader(bytes.NewReader(frame)) header, err := ReadHeader(reader) if err != nil || header != expected { t.Fatalf("header=%+v err=%v", header, err) } var artifact bytes.Buffer if err = CopyArtifact(&artifact, reader, header, 1<<20); err != nil { t.Fatal(err) } if artifact.String() != "artifact" { t.Fatalf("artifact=%q", artifact.String()) } } func TestProtocolRejectsTrailingAndForgedInputs(t *testing.T) { frame, header := validFrame(t, "artifact") reader := bufio.NewReader(bytes.NewReader(append(frame, 'x'))) read, _ := ReadHeader(reader) if err := CopyArtifact(&bytes.Buffer{}, reader, read, 1<<20); err == nil { t.Fatal("accepted trailing bytes") } header.Service = "../../root" if _, err := Prefix(header); err == nil { t.Fatal("accepted forged service") } header.Service = "example-site" header.ApprovedSHA256 = strings.Repeat("0", 64) if _, err := Prefix(header); err == nil { t.Fatal("accepted unapproved digest") } } func FuzzProtocolFraming(f *testing.F) { hash := sha256.Sum256([]byte("artifact")) digest := hex.EncodeToString(hash[:]) prefix, err := Prefix(Header{Protocol: Protocol, Service: "example-site", ArtifactName: "example.tar.gz", Size: 8, SHA256: digest, ApprovedSHA256: digest}) if err != nil { f.Fatal(err) } frame := append(prefix, []byte("artifact")...) f.Add(frame) f.Add([]byte{0, 0, 0, 0}) f.Fuzz(func(t *testing.T, input []byte) { if len(input) > 2<<20 { t.Skip() } reader := bufio.NewReader(bytes.NewReader(input)) header, err := ReadHeader(reader) if err != nil { return } _ = CopyArtifact(&bytes.Buffer{}, reader, header, 1<<20) }) }