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 }