...

Source file src/golang.org/x/crypto/openpgp/packet/reader.go

Documentation: golang.org/x/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  	"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  

View as plain text