From f54bb8daab9190b951d9b48f932e40fc3151d0e2 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Wed, 25 Mar 2020 00:25:17 -0400 Subject: [PATCH] internal/format: don't generate and reject empty lines in recipient bodies Detected by https://github.com/str4d/rage/runs/532262359 and by go-fuzz. --- cmd/age/age_test.go | 47 +++++++++++++++++++ cmd/age/testdata/empty_recipient_body.age | 6 +++ cmd/age/testdata/empty_recipient_body_key.txt | 7 +++ internal/format/format.go | 6 +++ 4 files changed, 66 insertions(+) create mode 100644 cmd/age/age_test.go create mode 100644 cmd/age/testdata/empty_recipient_body.age create mode 100644 cmd/age/testdata/empty_recipient_body_key.txt diff --git a/cmd/age/age_test.go b/cmd/age/age_test.go new file mode 100644 index 0000000..8799887 --- /dev/null +++ b/cmd/age/age_test.go @@ -0,0 +1,47 @@ +// Copyright 2019 Google LLC +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +package main + +import ( + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + + "filippo.io/age/internal/age" +) + +func TestVectors(t *testing.T) { + files, _ := filepath.Glob("testdata/*.age") + for _, f := range files { + name := strings.TrimSuffix(strings.TrimPrefix(f, "testdata/"), ".age") + t.Run(name, func(t *testing.T) { + identities, err := parseIdentitiesFile("testdata/" + name + "_key.txt") + if err != nil { + t.Fatal(err) + } + for _, i := range identities { + t.Logf("%s", i.Type()) + } + + in, err := os.Open("testdata/" + name + ".age") + if err != nil { + t.Fatal(err) + } + r, err := age.Decrypt(in, identities...) + if err != nil { + t.Fatal(err) + } + out, err := ioutil.ReadAll(r) + if err != nil { + t.Fatal(err) + } + t.Logf("%s", out) + }) + } +} diff --git a/cmd/age/testdata/empty_recipient_body.age b/cmd/age/testdata/empty_recipient_body.age new file mode 100644 index 0000000..55769e9 --- /dev/null +++ b/cmd/age/testdata/empty_recipient_body.age @@ -0,0 +1,6 @@ +age-encryption.org/v1 +-> ssh-ed25519 o1Hudg SZISkI5Qn8YgUBmTKG/Zp/QpFjXWvAivzvB+hOcN5W8 +dYfwGWYvCwpSU5EXIC1XqfXdsBvCi3kMypdqCVShrpk +-> joint-oil-hw +--- gC/27VAgqOEzAQMKHvBjih7sJ1oDKht+HNdguTIbjt8 +fëtAeµÖ¨&8{Ëéðνcat—íΘœ¯šË·}«=šC†Ÿu \ No newline at end of file diff --git a/cmd/age/testdata/empty_recipient_body_key.txt b/cmd/age/testdata/empty_recipient_body_key.txt new file mode 100644 index 0000000..a91b78c --- /dev/null +++ b/cmd/age/testdata/empty_recipient_body_key.txt @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACAwKgrb/LkvtI887QylSoUh5xUlKr1fb37euR6et5jHowAAAJgxqUx+MalM +fgAAAAtzc2gtZWQyNTUxOQAAACAwKgrb/LkvtI887QylSoUh5xUlKr1fb37euR6et5jHow +AAAEC7gKj74YIwaM1BT2tnODjfeZJvo8lcazvL6Uljv3+nIDAqCtv8uS+0jzztDKVKhSHn +FSUqvV9vft65Hp63mMejAAAADnJ1bm5lckBmdi1hejMyAQIDBAUGBw== +-----END OPENSSH PRIVATE KEY----- diff --git a/internal/format/format.go b/internal/format/format.go index 0aa60cd..a74e031 100644 --- a/internal/format/format.go +++ b/internal/format/format.go @@ -60,6 +60,9 @@ func (r *Recipient) Marshal(w io.Writer) error { if _, err := io.WriteString(w, "\n"); err != nil { return err } + if len(r.Body) == 0 { + return nil + } ww := base64.NewEncoder(b64, &newlineWriter{dst: w}) if _, err := ww.Write(r.Body); err != nil { return err @@ -160,6 +163,9 @@ func Parse(input io.Reader) (*Header, io.Reader, error) { if len(b) > bytesPerLine { return nil, nil, errorf("malformed body line %q: too long", line) } + if len(b) == 0 { + return nil, nil, errorf("malformed body line %q: line is empty", line) + } r.Body = append(r.Body, b...) if len(b) < bytesPerLine { // Only the last line of a body can be short.