mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 12:46:46 +00:00
Other: fix custom message on decryption error for externally encrypted message
This commit is contained in:
committed by
James Houlahan
parent
14d42b5e76
commit
ebf724412b
@ -291,7 +291,7 @@ func (matcher decryptsToMatcher) match(t *testing.T, have string) {
|
||||
dec, err := matcher.kr.Decrypt(haveMsg, nil, crypto.GetUnixTime())
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, matcher.want, dec.GetString())
|
||||
assert.Equal(t, matcher.want, string(dec.GetBinary()))
|
||||
}
|
||||
|
||||
func decryptsTo(kr *crypto.KeyRing, want string) decryptsToMatcher {
|
||||
|
||||
@ -40,7 +40,7 @@ func buildRFC822(kr *crypto.KeyRing, msg *pmapi.Message, attData [][]byte, opts
|
||||
return buildMultipartRFC822(kr, msg, attData, opts)
|
||||
|
||||
case msg.MIMEType == "multipart/mixed":
|
||||
return buildEncryptedRFC822(kr, msg, opts)
|
||||
return buildExternallyEncryptedRFC822(kr, msg, opts)
|
||||
|
||||
default:
|
||||
return buildSimpleRFC822(kr, msg, opts)
|
||||
@ -146,25 +146,10 @@ func writeTextPart(
|
||||
return errors.Wrap(ErrDecryptionFailed, err.Error())
|
||||
}
|
||||
|
||||
/*
|
||||
if len(msg.Attachments) > 0 {
|
||||
return writeCustomTextPartAsAttachment(w, msg, err)
|
||||
}
|
||||
*/
|
||||
|
||||
return writeCustomTextPart(w, msg, err)
|
||||
}
|
||||
|
||||
part, err := w.CreatePart(getTextPartHeader(message.Header{}, dec, msg.MIMEType))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := part.Write(dec); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return part.Close()
|
||||
return writePart(w, getTextPartHeader(message.Header{}, dec, msg.MIMEType), dec)
|
||||
}
|
||||
|
||||
func writeAttachmentPart(
|
||||
@ -196,16 +181,7 @@ func writeAttachmentPart(
|
||||
return writeCustomAttachmentPart(w, att, msg, err)
|
||||
}
|
||||
|
||||
part, err := w.CreatePart(getAttachmentPartHeader(att))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := part.Write(dec.GetBinary()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return part.Close()
|
||||
return writePart(w, getAttachmentPartHeader(att), dec.GetBinary())
|
||||
}
|
||||
|
||||
func writeRelatedParts(
|
||||
@ -221,25 +197,31 @@ func writeRelatedParts(
|
||||
|
||||
hdr.SetContentType("multipart/related", map[string]string{"boundary": boundary.gen()})
|
||||
|
||||
rel, err := w.CreatePart(hdr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := writeTextPart(rel, kr, msg, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i, att := range atts {
|
||||
if err := writeAttachmentPart(rel, kr, att, attData[i], opts); err != nil {
|
||||
return createPart(w, hdr, func(rel *message.Writer) error {
|
||||
if err := writeTextPart(rel, kr, msg, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return rel.Close()
|
||||
for i, att := range atts {
|
||||
if err := writeAttachmentPart(rel, kr, att, attData[i], opts); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func buildEncryptedRFC822(kr *crypto.KeyRing, msg *pmapi.Message, opts JobOptions) ([]byte, error) {
|
||||
func buildExternallyEncryptedRFC822(kr *crypto.KeyRing, msg *pmapi.Message, opts JobOptions) ([]byte, error) {
|
||||
dec, err := msg.Decrypt(kr)
|
||||
if err != nil {
|
||||
if !opts.IgnoreDecryptionErrors {
|
||||
return nil, errors.Wrap(ErrDecryptionFailed, err.Error())
|
||||
}
|
||||
|
||||
return buildPGPMIMERFC822(msg)
|
||||
}
|
||||
|
||||
hdr := getMessageHeader(msg, opts)
|
||||
|
||||
hdr.SetContentType("multipart/mixed", map[string]string{"boundary": newBoundary(msg.ID).gen()})
|
||||
@ -251,31 +233,58 @@ func buildEncryptedRFC822(kr *crypto.KeyRing, msg *pmapi.Message, opts JobOption
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dec, err := msg.Decrypt(kr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ErrDecryptionFailed, err.Error())
|
||||
}
|
||||
|
||||
ent, err := message.Read(bytes.NewReader(dec))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
part, err := w.CreatePart(ent.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(ent.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := part.Write(body); err != nil {
|
||||
if err := writePart(w, ent.Header, body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := part.Close(); err != nil {
|
||||
if err := w.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func buildPGPMIMERFC822(msg *pmapi.Message) ([]byte, error) {
|
||||
var hdr message.Header
|
||||
|
||||
hdr.SetContentType("multipart/encrypted", map[string]string{
|
||||
"boundary": newBoundary(msg.ID).gen(),
|
||||
"protocol": "application/pgp-encrypted",
|
||||
})
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
w, err := message.CreateWriter(buf, hdr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var encHdr message.Header
|
||||
|
||||
encHdr.SetContentType("application/pgp-encrypted", nil)
|
||||
encHdr.Set("Content-Description", "PGP/MIME version identification")
|
||||
|
||||
if err := writePart(w, encHdr, []byte("Version: 1")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dataHdr message.Header
|
||||
|
||||
dataHdr.SetContentType("application/octet-stream", map[string]string{"name": "encrypted.asc"})
|
||||
dataHdr.SetContentDisposition("inline", map[string]string{"filename": "encrypted.asc"})
|
||||
dataHdr.Set("Content-Description", "OpenPGP encrypted message")
|
||||
|
||||
if err := writePart(w, dataHdr, []byte(msg.Body)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -432,3 +441,26 @@ func toAddressList(addrs []*mail.Address) string {
|
||||
|
||||
return strings.Join(res, ", ")
|
||||
}
|
||||
|
||||
func createPart(w *message.Writer, hdr message.Header, fn func(*message.Writer) error) error {
|
||||
part, err := w.CreatePart(hdr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := fn(part); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return part.Close()
|
||||
}
|
||||
|
||||
func writePart(w *message.Writer, hdr message.Header, body []byte) error {
|
||||
return createPart(w, hdr, func(part *message.Writer) error {
|
||||
if _, err := part.Write(body); err != nil {
|
||||
return errors.Wrap(err, "failed to write part body")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -1008,6 +1008,48 @@ func TestBuildCustomMessageHTML(t *testing.T) {
|
||||
expectTransferEncoding(isMissing())
|
||||
}
|
||||
|
||||
func TestBuildCustomMessageEncrypted(t *testing.T) {
|
||||
m := gomock.NewController(t)
|
||||
defer m.Finish()
|
||||
|
||||
b := NewBuilder(1, 1, 1)
|
||||
defer b.Done()
|
||||
|
||||
kr := tests.MakeKeyRing(t)
|
||||
|
||||
body := readerToString(getFileReader("pgp-mime-body-plaintext.eml"))
|
||||
|
||||
// Use a different keyring for encrypting the message; it won't be decryptable.
|
||||
foreignKR := tests.MakeKeyRing(t)
|
||||
msg := newTestMessage(t, foreignKR, "messageID", "addressID", "multipart/mixed", body, time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
// Tell the job to ignore decryption errors; a custom message will be returned instead of an error.
|
||||
res, err := b.NewJobWithOptions(
|
||||
context.Background(),
|
||||
newTestFetcher(m, kr, msg),
|
||||
msg.ID,
|
||||
JobOptions{IgnoreDecryptionErrors: true},
|
||||
).GetResult()
|
||||
require.NoError(t, err)
|
||||
|
||||
section(t, res).
|
||||
expectContentType(is(`multipart/encrypted`)).
|
||||
expectContentTypeParam(`protocol`, is(`application/pgp-encrypted`))
|
||||
|
||||
section(t, res, 1).
|
||||
expectContentType(is(`application/pgp-encrypted`)).
|
||||
expectHeader(`Content-Description`, is(`PGP/MIME version identification`)).
|
||||
expectBody(is(`Version: 1`))
|
||||
|
||||
section(t, res, 2).
|
||||
expectContentType(is(`application/octet-stream`)).
|
||||
expectContentTypeParam(`name`, is(`encrypted.asc`)).
|
||||
expectContentDisposition(is(`inline`)).
|
||||
expectContentDispositionParam(`filename`, is(`encrypted.asc`)).
|
||||
expectHeader(`Content-Description`, is(`OpenPGP encrypted message`)).
|
||||
expectBody(decryptsTo(foreignKR, body))
|
||||
}
|
||||
|
||||
func TestBuildCustomMessagePlainWithAttachment(t *testing.T) {
|
||||
m := gomock.NewController(t)
|
||||
defer m.Finish()
|
||||
|
||||
Reference in New Issue
Block a user