main
Raw Download raw file
  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	"io"
  9
 10	"github.com/ProtonMail/go-crypto/openpgp/errors"
 11)
 12
 13type PacketReader interface {
 14	Next() (p Packet, err error)
 15	Push(reader io.Reader) (err error)
 16	Unread(p Packet)
 17}
 18
 19// Reader reads packets from an io.Reader and allows packets to be 'unread' so
 20// that they result from the next call to Next.
 21type Reader struct {
 22	q       []Packet
 23	readers []io.Reader
 24}
 25
 26// New io.Readers are pushed when a compressed or encrypted packet is processed
 27// and recursively treated as a new source of packets. However, a carefully
 28// crafted packet can trigger an infinite recursive sequence of packets. See
 29// http://mumble.net/~campbell/misc/pgp-quine
 30// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402
 31// This constant limits the number of recursive packets that may be pushed.
 32const maxReaders = 32
 33
 34// Next returns the most recently unread Packet, or reads another packet from
 35// the top-most io.Reader. Unknown/unsupported/Marker packet types are skipped.
 36func (r *Reader) Next() (p Packet, err error) {
 37	for {
 38		p, err := r.read()
 39		if err == io.EOF {
 40			break
 41		} else if err != nil {
 42			if _, ok := err.(errors.UnknownPacketTypeError); ok {
 43				continue
 44			}
 45			if _, ok := err.(errors.UnsupportedError); ok {
 46				switch p.(type) {
 47				case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData:
 48					return nil, err
 49				}
 50				continue
 51			}
 52			return nil, err
 53		} else {
 54			//A marker packet MUST be ignored when received
 55			switch p.(type) {
 56			case *Marker:
 57				continue
 58			}
 59			return p, nil
 60		}
 61	}
 62	return nil, io.EOF
 63}
 64
 65// Next returns the most recently unread Packet, or reads another packet from
 66// the top-most io.Reader. Unknown/Marker packet types are skipped while unsupported
 67// packets are returned as UnsupportedPacket type.
 68func (r *Reader) NextWithUnsupported() (p Packet, err error) {
 69	for {
 70		p, err = r.read()
 71		if err == io.EOF {
 72			break
 73		} else if err != nil {
 74			if _, ok := err.(errors.UnknownPacketTypeError); ok {
 75				continue
 76			}
 77			if casteErr, ok := err.(errors.UnsupportedError); ok {
 78				return &UnsupportedPacket{
 79					IncompletePacket: p,
 80					Error:            casteErr,
 81				}, nil
 82			}
 83			return
 84		} else {
 85			//A marker packet MUST be ignored when received
 86			switch p.(type) {
 87			case *Marker:
 88				continue
 89			}
 90			return
 91		}
 92	}
 93	return nil, io.EOF
 94}
 95
 96func (r *Reader) read() (p Packet, err error) {
 97	if len(r.q) > 0 {
 98		p = r.q[len(r.q)-1]
 99		r.q = r.q[:len(r.q)-1]
100		return
101	}
102	for len(r.readers) > 0 {
103		p, err = Read(r.readers[len(r.readers)-1])
104		if err == io.EOF {
105			r.readers = r.readers[:len(r.readers)-1]
106			continue
107		}
108		return p, err
109	}
110	return nil, io.EOF
111}
112
113// Push causes the Reader to start reading from a new io.Reader. When an EOF
114// error is seen from the new io.Reader, it is popped and the Reader continues
115// to read from the next most recent io.Reader. Push returns a StructuralError
116// if pushing the reader would exceed the maximum recursion level, otherwise it
117// returns nil.
118func (r *Reader) Push(reader io.Reader) (err error) {
119	if len(r.readers) >= maxReaders {
120		return errors.StructuralError("too many layers of packets")
121	}
122	r.readers = append(r.readers, reader)
123	return nil
124}
125
126// Unread causes the given Packet to be returned from the next call to Next.
127func (r *Reader) Unread(p Packet) {
128	r.q = append(r.q, p)
129}
130
131func NewReader(r io.Reader) *Reader {
132	return &Reader{
133		q:       nil,
134		readers: []io.Reader{r},
135	}
136}
137
138// CheckReader is similar to Reader but additionally
139// uses the pushdown automata to verify the read packet sequence.
140type CheckReader struct {
141	Reader
142	verifier  *SequenceVerifier
143	fullyRead bool
144}
145
146// Next returns the most recently unread Packet, or reads another packet from
147// the top-most io.Reader. Unknown packet types are skipped.
148// If the read packet sequence does not conform to the packet composition
149// rules in rfc4880, it returns an error.
150func (r *CheckReader) Next() (p Packet, err error) {
151	if r.fullyRead {
152		return nil, io.EOF
153	}
154	if len(r.q) > 0 {
155		p = r.q[len(r.q)-1]
156		r.q = r.q[:len(r.q)-1]
157		return
158	}
159	var errMsg error
160	for len(r.readers) > 0 {
161		p, errMsg, err = ReadWithCheck(r.readers[len(r.readers)-1], r.verifier)
162		if errMsg != nil {
163			err = errMsg
164			return
165		}
166		if err == nil {
167			return
168		}
169		if err == io.EOF {
170			r.readers = r.readers[:len(r.readers)-1]
171			continue
172		}
173		//A marker packet MUST be ignored when received
174		switch p.(type) {
175		case *Marker:
176			continue
177		}
178		if _, ok := err.(errors.UnknownPacketTypeError); ok {
179			continue
180		}
181		if _, ok := err.(errors.UnsupportedError); ok {
182			switch p.(type) {
183			case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData:
184				return nil, err
185			}
186			continue
187		}
188		return nil, err
189	}
190	if errMsg = r.verifier.Next(EOSSymbol); errMsg != nil {
191		return nil, errMsg
192	}
193	if errMsg = r.verifier.AssertValid(); errMsg != nil {
194		return nil, errMsg
195	}
196	r.fullyRead = true
197	return nil, io.EOF
198}
199
200func NewCheckReader(r io.Reader) *CheckReader {
201	return &CheckReader{
202		Reader: Reader{
203			q:       nil,
204			readers: []io.Reader{r},
205		},
206		verifier:  NewSequenceVerifier(),
207		fullyRead: false,
208	}
209}