1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package packet 6 7 import ( 8 "golang.org/x/crypto/openpgp/errors" 9 "io" 10 ) 11 12 // Reader reads packets from an io.Reader and allows packets to be 'unread' so 13 // that they result from the next call to Next. 14 type Reader struct { 15 q []Packet 16 readers []io.Reader 17 } 18 19 // New io.Readers are pushed when a compressed or encrypted packet is processed 20 // and recursively treated as a new source of packets. However, a carefully 21 // crafted packet can trigger an infinite recursive sequence of packets. See 22 // http://mumble.net/~campbell/misc/pgp-quine 23 // https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402 24 // This constant limits the number of recursive packets that may be pushed. 25 const maxReaders = 32 26 27 // Next returns the most recently unread Packet, or reads another packet from 28 // the top-most io.Reader. Unknown packet types are skipped. 29 func (r *Reader) Next() (p Packet, err error) { 30 if len(r.q) > 0 { 31 p = r.q[len(r.q)-1] 32 r.q = r.q[:len(r.q)-1] 33 return 34 } 35 36 for len(r.readers) > 0 { 37 p, err = Read(r.readers[len(r.readers)-1]) 38 if err == nil { 39 return 40 } 41 if err == io.EOF { 42 r.readers = r.readers[:len(r.readers)-1] 43 continue 44 } 45 if _, ok := err.(errors.UnknownPacketTypeError); !ok { 46 return nil, err 47 } 48 } 49 50 return nil, io.EOF 51 } 52 53 // Push causes the Reader to start reading from a new io.Reader. When an EOF 54 // error is seen from the new io.Reader, it is popped and the Reader continues 55 // to read from the next most recent io.Reader. Push returns a StructuralError 56 // if pushing the reader would exceed the maximum recursion level, otherwise it 57 // returns nil. 58 func (r *Reader) Push(reader io.Reader) (err error) { 59 if len(r.readers) >= maxReaders { 60 return errors.StructuralError("too many layers of packets") 61 } 62 r.readers = append(r.readers, reader) 63 return nil 64 } 65 66 // Unread causes the given Packet to be returned from the next call to Next. 67 func (r *Reader) Unread(p Packet) { 68 r.q = append(r.q, p) 69 } 70 71 func NewReader(r io.Reader) *Reader { 72 return &Reader{ 73 q: nil, 74 readers: []io.Reader{r}, 75 } 76 } 77