openpgp: remove TeeReader from packet.Read
This is a followup to issue 6927044. I *really* don't want to break streaming for large encrypted data packets. Removing the automatic re-parsing. OpaqueReader can be used for recovering useful information from mangled/unsupported packets. R=agl CC=golang-dev https://golang.org/cl/6944056
This commit is contained in:
committed by
Adam Langley
parent
61ab4d36df
commit
50ff460fe1
@@ -46,9 +46,15 @@ func (op *OpaquePacket) Parse() (p Packet, err error) {
|
||||
hdr := bytes.NewBuffer(nil)
|
||||
err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents))
|
||||
if err != nil {
|
||||
op.Reason = err
|
||||
return op, err
|
||||
}
|
||||
return Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents)))
|
||||
p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents)))
|
||||
if err != nil {
|
||||
op.Reason = err
|
||||
p = op
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OpaqueReader reads OpaquePackets from an io.Reader.
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package packet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.google.com/p/go.crypto/openpgp/armor"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// This key contains version 2 public key and signature packets.
|
||||
// If these are ever supported, this test will need to be updated
|
||||
// with bad packets that won't parse.
|
||||
const UnsupportedKeyArmor = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: SKS 1.0.10
|
||||
|
||||
mI0CLnoYogAAAQQA1qwA2SuJwfQ5bCQ6u5t20ulnOtY0gykf7YjiK4LiVeRBwHjGq7v30tGV
|
||||
5Qti7qqRW4Ww7CDCJc4sZMFnystucR2vLkXaSoNWoFm4Fg47NiisDdhDezHwbVPW6OpCFNSi
|
||||
ZAamtj4QAUBu8j4LswafrJqZqR9336/V3g8Yil2l48kABRG0J0FybWluIE0uIFdhcmRhIDx3
|
||||
YXJkYUBuZXBoaWxpbS5ydWhyLmRlPoiVAgUQLok2xwXR6zmeWEiZAQE/DgP/WgxPQh40/Po4
|
||||
gSkWZCDAjNdph7zexvAb0CcUWahcwiBIgg3U5ErCx9I5CNVA9U+s8bNrDZwgSIeBzp3KhWUx
|
||||
524uhGgm6ZUTOAIKA6CbV6pfqoLpJnRYvXYQU5mIWsNa99wcu2qu18OeEDnztb7aLA6Ra9OF
|
||||
YFCbq4EjXRoOrYM=
|
||||
=LPjs
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
// Test packet.Read error handling in OpaquePacket.Parse,
|
||||
// which attempts to re-read an OpaquePacket as a supported
|
||||
// Packet type.
|
||||
func TestOpaqueParseReason(t *testing.T) {
|
||||
armorBlock, err := armor.Decode(bytes.NewBufferString(UnsupportedKeyArmor))
|
||||
if err != nil {
|
||||
t.Fatalf("armor Decode failed: %v", err)
|
||||
}
|
||||
or := NewOpaqueReader(armorBlock.Body)
|
||||
count := 0
|
||||
badPackets := 0
|
||||
var uid *UserId
|
||||
for {
|
||||
op, err := or.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
t.Errorf("#%d: opaque read error: %v", count, err)
|
||||
break
|
||||
}
|
||||
// try to parse opaque packet
|
||||
p, err := op.Parse()
|
||||
switch pkt := p.(type) {
|
||||
case *UserId:
|
||||
uid = pkt
|
||||
case *OpaquePacket:
|
||||
// If an OpaquePacket can't re-parse, packet.Read
|
||||
// certainly had its reasons.
|
||||
if pkt.Reason == nil {
|
||||
t.Errorf("#%d: opaque packet, no reason", count)
|
||||
} else {
|
||||
badPackets++
|
||||
}
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
const expectedBad = 2
|
||||
// Test post-conditions, make sure we actually parsed packets as expected.
|
||||
if badPackets != expectedBad {
|
||||
t.Errorf("unexpected # unparseable packets: %d (want %d)", badPackets, expectedBad)
|
||||
}
|
||||
if uid == nil {
|
||||
t.Errorf("failed to find expected UID in unsupported keyring")
|
||||
} else if uid.Id != "Armin M. Warda <warda@nephilim.ruhr.de>" {
|
||||
t.Errorf("unexpected UID: %v", uid.Id)
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.google.com/p/go.crypto/cast5"
|
||||
"code.google.com/p/go.crypto/openpgp/errors"
|
||||
"crypto/aes"
|
||||
@@ -339,23 +338,10 @@ func Read(r io.Reader) (p Packet, err error) {
|
||||
se.MDC = true
|
||||
p = se
|
||||
default:
|
||||
p = new(OpaquePacket)
|
||||
err = errors.UnknownPacketTypeError(tag)
|
||||
}
|
||||
if p != nil {
|
||||
backup := bytes.NewBuffer(nil)
|
||||
// FIXME: this causes large packets to be buffered in memory.
|
||||
// Ideally we would like a better solution here so that huge,
|
||||
// encrypted files could still be handled in a streaming
|
||||
// fashion. Perhaps the encrypted data packet could call a
|
||||
// method on backup that causes it to stop recording.
|
||||
tee := io.TeeReader(contents, backup)
|
||||
err = p.parse(tee)
|
||||
switch err.(type) {
|
||||
case errors.UnsupportedError, errors.UnknownPacketTypeError:
|
||||
p = &OpaquePacket{Tag: uint8(tag), Reason: err}
|
||||
err = nil
|
||||
err = p.parse(io.MultiReader(backup, contents))
|
||||
}
|
||||
err = p.parse(contents)
|
||||
}
|
||||
if err != nil {
|
||||
consumeAll(contents)
|
||||
|
||||
Reference in New Issue
Block a user