...

Source file src/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go

Documentation: github.com/ProtonMail/go-crypto/openpgp/packet

     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  	"io"
     9  
    10  	"github.com/ProtonMail/go-crypto/openpgp/errors"
    11  )
    12  
    13  // Reader reads packets from an io.Reader and allows packets to be 'unread' so
    14  // that they result from the next call to Next.
    15  type Reader struct {
    16  	q       []Packet
    17  	readers []io.Reader
    18  }
    19  
    20  // New io.Readers are pushed when a compressed or encrypted packet is processed
    21  // and recursively treated as a new source of packets. However, a carefully
    22  // crafted packet can trigger an infinite recursive sequence of packets. See
    23  // http://mumble.net/~campbell/misc/pgp-quine
    24  // https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402
    25  // This constant limits the number of recursive packets that may be pushed.
    26  const maxReaders = 32
    27  
    28  // Next returns the most recently unread Packet, or reads another packet from
    29  // the top-most io.Reader. Unknown packet types are skipped.
    30  func (r *Reader) Next() (p Packet, err error) {
    31  	if len(r.q) > 0 {
    32  		p = r.q[len(r.q)-1]
    33  		r.q = r.q[:len(r.q)-1]
    34  		return
    35  	}
    36  
    37  	for len(r.readers) > 0 {
    38  		p, err = Read(r.readers[len(r.readers)-1])
    39  		if err == nil {
    40  			return
    41  		}
    42  		if err == io.EOF {
    43  			r.readers = r.readers[:len(r.readers)-1]
    44  			continue
    45  		}
    46  		// TODO: Add strict mode that rejects unknown packets, instead of ignoring them.
    47  		if _, ok := err.(errors.UnknownPacketTypeError); ok {
    48  			continue
    49  		}
    50  		if _, ok := err.(errors.UnsupportedError); ok {
    51  			switch p.(type) {
    52  			case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData:
    53  				return nil, err
    54  			}
    55  			continue
    56  		}
    57  		return nil, err
    58  	}
    59  
    60  	return nil, io.EOF
    61  }
    62  
    63  // Push causes the Reader to start reading from a new io.Reader. When an EOF
    64  // error is seen from the new io.Reader, it is popped and the Reader continues
    65  // to read from the next most recent io.Reader. Push returns a StructuralError
    66  // if pushing the reader would exceed the maximum recursion level, otherwise it
    67  // returns nil.
    68  func (r *Reader) Push(reader io.Reader) (err error) {
    69  	if len(r.readers) >= maxReaders {
    70  		return errors.StructuralError("too many layers of packets")
    71  	}
    72  	r.readers = append(r.readers, reader)
    73  	return nil
    74  }
    75  
    76  // Unread causes the given Packet to be returned from the next call to Next.
    77  func (r *Reader) Unread(p Packet) {
    78  	r.q = append(r.q, p)
    79  }
    80  
    81  func NewReader(r io.Reader) *Reader {
    82  	return &Reader{
    83  		q:       nil,
    84  		readers: []io.Reader{r},
    85  	}
    86  }
    87  

View as plain text