From 085cf20de98c8b7008434f4fb3287fa6c5a16195b32c4e58f2cbd95bc3caac1d Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 9 Jan 2025 18:02:23 +0300 Subject: [PATCH] Initial commit --- go.mod | 3 ++ main.go | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 go.mod create mode 100644 main.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..bfc15c6 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module go.stargrave.org/pgpmaildecryptor + +go 1.23.4 diff --git a/main.go b/main.go new file mode 100644 index 0000000..50dd1d9 --- /dev/null +++ b/main.go @@ -0,0 +1,136 @@ +package main + +import ( + "bufio" + "bytes" + "io" + "log" + "mime" + "net/mail" + "net/textproto" + "os" + "os/exec" + "strings" +) + +func main() { + log.SetFlags(log.Lshortfile) + rawEnc, err := io.ReadAll(bufio.NewReader(os.Stdin)) + if err != nil { + log.Fatal(err) + } + msgEnc, err := mail.ReadMessage(bytes.NewReader(rawEnc)) + if err != nil { + log.Fatal(err) + } + { + ct := msgEnc.Header.Get("Content-Type") + if ct == "" { + log.Fatal("no Content-Type") + } + mt, params, errParse := mime.ParseMediaType(ct) + if errParse != nil { + log.Fatal(errParse) + } + if mt != "multipart/encrypted" { + log.Fatal("not multipart/encrypted") + } + if proto := params["protocol"]; proto != "application/pgp-encrypted" { + log.Fatal("not application/pgp-encrypted") + } + } + var rawDec []byte + { + cmd := exec.Command("gpg", "--batch", "--decrypt", "--status-fd", "3") + cmd.Stderr = os.Stderr + var stdin io.WriteCloser + stdin, err = cmd.StdinPipe() + if err != nil { + log.Fatal(err) + } + var stdout io.ReadCloser + stdout, err = cmd.StdoutPipe() + if err != nil { + log.Fatal(err) + } + var statusR, statusW *os.File + statusR, statusW, err = os.Pipe() + if err != nil { + log.Fatal(err) + } + cmd.ExtraFiles = append(cmd.ExtraFiles, statusW) + + err = cmd.Start() + if err != nil { + log.Fatal(err) + } + go func() { + _, errStdin := io.Copy(stdin, msgEnc.Body) + if err != nil { + log.Print(errStdin) + } + if errStdin = stdin.Close(); err != nil { + log.Print(errStdin) + } + }() + var goodDec bool + go func() { + s := bufio.NewScanner(statusR) + var t string + for s.Scan() { + t = s.Text() + if t == "[GNUPG:] DECRYPTION_OKAY" { + goodDec = true + } + log.Print(t) + } + if s.Err() != nil { + log.Print(s.Err()) + } + }() + rawDec, err = io.ReadAll(stdout) + if err != nil { + log.Fatal(err) + } + err = cmd.Wait() + if err != nil { + log.Fatal(err) + } + if !goodDec { + log.Fatal("no DECRYPTION_OKAY received") + } + } + msgDec, err := mail.ReadMessage(bytes.NewReader(rawDec)) + if err != nil { + log.Fatal(err) + } + stdout := bufio.NewWriter(os.Stdout) + r := textproto.NewReader(bufio.NewReader(bytes.NewReader(rawEnc))) + var t string + var hdr string + for { + t, err = r.ReadContinuedLine() + if err != nil { + log.Fatal(err) + } + if t == "" { + break + } + hdr = t[:strings.Index(t, ":")] + if msgDec.Header.Get(hdr) != "" { + continue + } + if _, err = stdout.WriteString(t); err != nil { + log.Fatal(err) + } + if _, err = stdout.WriteString("\n"); err != nil { + log.Fatal(err) + } + } + if _, err = io.Copy(stdout, bytes.NewReader(rawDec)); err != nil { + log.Fatal(err) + } + if err = stdout.Flush(); err != nil { + log.Fatal(err) + } +} -- 2.48.1