diff --git a/plugin/client.go b/plugin/client.go index dca1a52..5e96006 100644 --- a/plugin/client.go +++ b/plugin/client.go @@ -79,7 +79,7 @@ func (r *Recipient) WrapWithLabels(fileKey []byte) (stanzas []*age.Stanza, label if err := writeStanza(conn, addType, r.encoding); err != nil { return nil, nil, err } - if err := writeStanza(conn, fmt.Sprintf("grease-%x", rand.Int())); err != nil { + if _, err := writeGrease(conn); err != nil { return nil, nil, err } if err := writeStanzaWithBody(conn, "wrap-file-key", fileKey); err != nil { @@ -220,7 +220,7 @@ func (i *Identity) Unwrap(stanzas []*age.Stanza) (fileKey []byte, err error) { if err := writeStanza(conn, "add-identity", i.encoding); err != nil { return nil, err } - if err := writeStanza(conn, fmt.Sprintf("grease-%x", rand.Int())); err != nil { + if _, err := writeGrease(conn); err != nil { return nil, err } for _, rs := range stanzas { @@ -449,3 +449,18 @@ func writeStanzaWithBody(conn io.Writer, t string, body []byte) error { s := &format.Stanza{Type: t, Body: body} return s.Marshal(conn) } + +func writeGrease(conn io.Writer) (sent bool, err error) { + if rand.Intn(3) == 0 { + return false, nil + } + s := &format.Stanza{Type: fmt.Sprintf("grease-%x", rand.Int())} + for i := 0; i < rand.Intn(3); i++ { + s.Args = append(s.Args, fmt.Sprintf("%d", rand.Intn(100))) + } + if rand.Intn(2) == 0 { + s.Body = make([]byte, rand.Intn(100)) + rand.Read(s.Body) + } + return true, s.Marshal(conn) +} diff --git a/plugin/plugin.go b/plugin/plugin.go index 5a265d8..55c697b 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -251,6 +251,14 @@ ReadLoop: } } + if sent, err := writeGrease(os.Stdout); err != nil { + return fatalf("failed to write grease: %v", err) + } else if sent { + if err := expectUnsupported(sr); err != nil { + return fatalf("%v", err) + } + } + if supportsLabels { if err := writeStanza(os.Stdout, "labels", labels...); err != nil { return fatalf("failed to write labels stanza: %v", err) @@ -271,6 +279,13 @@ ReadLoop: return fatalf("%v", err) } } + if sent, err := writeGrease(os.Stdout); err != nil { + return fatalf("failed to write grease: %v", err) + } else if sent { + if err := expectUnsupported(sr); err != nil { + return fatalf("%v", err) + } + } } if err := writeStanza(os.Stdout, "done"); err != nil { @@ -374,6 +389,14 @@ ReadLoop: } for i, ss := range files { + if sent, err := writeGrease(os.Stdout); err != nil { + return fatalf("failed to write grease: %v", err) + } else if sent { + if err := expectUnsupported(sr); err != nil { + return fatalf("%v", err) + } + } + // TODO: there should be a mechanism to let the plugin decide the order // in which identities are tried. for _, id := range identities { @@ -451,6 +474,17 @@ func expectOk(sr *format.StanzaReader) error { return expectStanzaWithNoBody(ok, 0) } +func expectUnsupported(sr *format.StanzaReader) error { + unsupported, err := sr.ReadStanza() + if err != nil { + return fmt.Errorf("failed to read unsupported stanza: %v", err) + } + if unsupported.Type != "unsupported" { + return fmt.Errorf("expected unsupported stanza, got %q", unsupported.Type) + } + return expectStanzaWithNoBody(unsupported, 0) +} + func writeError(sr *format.StanzaReader, args []string, err error) error { s := &format.Stanza{Type: "error", Args: args} s.Body = []byte(err.Error())