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 5package packet 6 7import ( 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. 14type 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. 25const 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. 29func (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. 58func (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. 67func (r *Reader) Unread(p Packet) { 68 r.q = append(r.q, p) 69} 70 71func NewReader(r io.Reader) *Reader { 72 return &Reader{ 73 q: nil, 74 readers: []io.Reader{r}, 75 } 76} 77