github.com/alejandroesc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy3/frames/credential.go (about)

     1  // Copyright 2014 Jamie Hall. 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 frames
     6  
     7  import (
     8  	"bytes"
     9  	"crypto/x509"
    10  	"fmt"
    11  	"io"
    12  
    13  	"github.com/SlyMarbo/spdy/common"
    14  )
    15  
    16  type CREDENTIAL struct {
    17  	Slot         uint16
    18  	Proof        []byte
    19  	Certificates []*x509.Certificate
    20  }
    21  
    22  func (frame *CREDENTIAL) Compress(comp common.Compressor) error {
    23  	return nil
    24  }
    25  
    26  func (frame *CREDENTIAL) Decompress(decomp common.Decompressor) error {
    27  	return nil
    28  }
    29  
    30  func (frame *CREDENTIAL) Name() string {
    31  	return "CREDENTIAL"
    32  }
    33  
    34  func (frame *CREDENTIAL) ReadFrom(reader io.Reader) (int64, error) {
    35  	c := common.ReadCounter{R: reader}
    36  	data, err := common.ReadExactly(&c, 18)
    37  	if err != nil {
    38  		return c.N, err
    39  	}
    40  
    41  	err = controlFrameCommonProcessing(data[:5], _CREDENTIAL, 0)
    42  	if err != nil {
    43  		return c.N, err
    44  	}
    45  
    46  	// Get and check length.
    47  	length := int(common.BytesToUint24(data[5:8]))
    48  	if length < 6 {
    49  		return c.N, common.IncorrectDataLength(length, 6)
    50  	} else if length > common.MAX_FRAME_SIZE-8 {
    51  		return c.N, common.FrameTooLarge
    52  	}
    53  
    54  	// Read in data.
    55  	certs, err := common.ReadExactly(&c, length-10)
    56  	if err != nil {
    57  		return c.N, err
    58  	}
    59  
    60  	frame.Slot = common.BytesToUint16(data[8:10])
    61  	proofLen := int(common.BytesToUint32(data[10:14]))
    62  	if proofLen > 0 {
    63  		frame.Proof = data[14 : 14+proofLen]
    64  	} else {
    65  		frame.Proof = []byte{}
    66  	}
    67  
    68  	numCerts := 0
    69  	for offset := 0; offset < length-10; {
    70  		offset += int(common.BytesToUint32(certs[offset:offset+4])) + 4
    71  		numCerts++
    72  	}
    73  
    74  	frame.Certificates = make([]*x509.Certificate, numCerts)
    75  	for i, offset := 0, 0; offset < length-10; i++ {
    76  		length := int(common.BytesToUint32(certs[offset : offset+4]))
    77  		rawCert := certs[offset+4 : offset+4+length]
    78  		frame.Certificates[i], err = x509.ParseCertificate(rawCert)
    79  		if err != nil {
    80  			return c.N, err
    81  		}
    82  		offset += length + 4
    83  	}
    84  
    85  	return c.N, nil
    86  }
    87  
    88  func (frame *CREDENTIAL) String() string {
    89  	buf := new(bytes.Buffer)
    90  
    91  	buf.WriteString("CREDENTIAL {\n\t")
    92  	buf.WriteString(fmt.Sprintf("Version:              3\n\t"))
    93  	buf.WriteString(fmt.Sprintf("Slot:                 %d\n\t", frame.Slot))
    94  	buf.WriteString(fmt.Sprintf("Proof:                %v\n\t", frame.Proof))
    95  	buf.WriteString(fmt.Sprintf("Certificates:         %v\n}\n", frame.Certificates))
    96  
    97  	return buf.String()
    98  }
    99  
   100  func (frame *CREDENTIAL) WriteTo(writer io.Writer) (int64, error) {
   101  	c := common.WriteCounter{W: writer}
   102  	proofLength := len(frame.Proof)
   103  	certsLength := 0
   104  	for _, cert := range frame.Certificates {
   105  		certsLength += len(cert.Raw)
   106  	}
   107  
   108  	length := 6 + proofLength + certsLength
   109  	out := make([]byte, 14)
   110  
   111  	out[0] = 128                      // Control bit and Version
   112  	out[1] = 3                        // Version
   113  	out[2] = 0                        // Type
   114  	out[3] = 10                       // Type
   115  	out[4] = 0                        // common.Flags
   116  	out[5] = byte(length >> 16)       // Length
   117  	out[6] = byte(length >> 8)        // Length
   118  	out[7] = byte(length)             // Length
   119  	out[8] = byte(frame.Slot >> 8)    // Slot
   120  	out[9] = byte(frame.Slot)         // Slot
   121  	out[10] = byte(proofLength >> 24) // Proof Length
   122  	out[11] = byte(proofLength >> 16) // Proof Length
   123  	out[12] = byte(proofLength >> 8)  // Proof Length
   124  	out[13] = byte(proofLength)       // Proof Length
   125  
   126  	err := common.WriteExactly(&c, out)
   127  	if err != nil {
   128  		return c.N, err
   129  	}
   130  
   131  	if len(frame.Proof) > 0 {
   132  		err = common.WriteExactly(&c, frame.Proof)
   133  		if err != nil {
   134  			return c.N, err
   135  		}
   136  	}
   137  
   138  	written := int64(14 + len(frame.Proof))
   139  	for _, cert := range frame.Certificates {
   140  		err = common.WriteExactly(&c, cert.Raw)
   141  		if err != nil {
   142  			return c.N, err
   143  		}
   144  		written += int64(len(cert.Raw))
   145  	}
   146  
   147  	return c.N, nil
   148  }