Skip to content

Commit

Permalink
Add cipher suite test to http2 interop tests, and honor test_case flag
Browse files Browse the repository at this point in the history
  • Loading branch information
carl-mastrangelo committed Nov 19, 2015
1 parent bef0d6d commit 8a1cdec
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 15 deletions.
72 changes: 72 additions & 0 deletions tools/http2_interop/goaway.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package http2interop

import (
"encoding/binary"
"fmt"
"io"
)

type GoAwayFrame struct {
Header FrameHeader
Reserved
StreamID
// TODO(carl-mastrangelo): make an enum out of this.
Code uint32
Data []byte
}

func (f *GoAwayFrame) GetHeader() *FrameHeader {
return &f.Header
}

func (f *GoAwayFrame) ParsePayload(r io.Reader) error {
raw := make([]byte, f.Header.Length)
if _, err := io.ReadFull(r, raw); err != nil {
return err
}
return f.UnmarshalPayload(raw)
}

func (f *GoAwayFrame) UnmarshalPayload(raw []byte) error {
if f.Header.Length != len(raw) {
return fmt.Errorf("Invalid Payload length %d != %d", f.Header.Length, len(raw))
}
if f.Header.Length < 8 {
return fmt.Errorf("Invalid Payload length %d", f.Header.Length)
}
*f = GoAwayFrame{
Reserved: Reserved(raw[0]>>7 == 1),
StreamID: StreamID(binary.BigEndian.Uint32(raw[0:4]) & 0x7fffffff),
Code: binary.BigEndian.Uint32(raw[4:8]),
Data: []byte(string(raw[8:])),
}

return nil
}

func (f *GoAwayFrame) MarshalPayload() ([]byte, error) {
raw := make([]byte, 8, 8+len(f.Data))
binary.BigEndian.PutUint32(raw[:4], uint32(f.StreamID))
binary.BigEndian.PutUint32(raw[4:8], f.Code)
raw = append(raw, f.Data...)

return raw, nil
}

func (f *GoAwayFrame) MarshalBinary() ([]byte, error) {
payload, err := f.MarshalPayload()
if err != nil {
return nil, err
}

f.Header.Length = len(payload)
f.Header.Type = GoAwayFrameType
header, err := f.Header.MarshalBinary()
if err != nil {
return nil, err
}

header = append(header, payload...)

return header, nil
}
52 changes: 52 additions & 0 deletions tools/http2_interop/http2interop.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,58 @@ func testTLSApplicationProtocol(ctx *HTTP2InteropCtx) error {
return nil
}

func testTLSBadCipherSuites(ctx *HTTP2InteropCtx) error {
config := buildTlsConfig(ctx)
// These are the suites that Go supports, but are forbidden by http2.
config.CipherSuites = []uint16{
tls.TLS_RSA_WITH_RC4_128_SHA,
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
}
conn, err := connectWithTls(ctx, config)
if err != nil {
return err
}
defer conn.Close()
conn.SetDeadline(time.Now().Add(defaultTimeout))

if err := http2Connect(conn, nil); err != nil {
return err
}

for {
f, err := parseFrame(conn)
if err != nil {
return err
}
if gf, ok := f.(*GoAwayFrame); ok {
return fmt.Errorf("Got goaway frame %d", gf.Code)
}
}
return nil
}

func http2Connect(c net.Conn, sf *SettingsFrame) error {
if _, err := c.Write([]byte(Preface)); err != nil {
return err
}
if sf == nil {
sf = &SettingsFrame{}
}
if err := streamFrame(c, sf); err != nil {
return err
}
return nil
}

func connect(ctx *HTTP2InteropCtx) (net.Conn, error) {
var conn net.Conn
var err error
Expand Down
46 changes: 31 additions & 15 deletions tools/http2_interop/http2interop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@ package http2interop
import (
"crypto/tls"
"crypto/x509"
"strings"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"strconv"
"strings"
"testing"
)

var (
serverHost = flag.String("server_host", "", "The host to test")
serverPort = flag.Int("server_port", 443, "The port to test")
useTls = flag.Bool("use_tls", true, "Should TLS tests be run")
// TODO: implement
testCase = flag.String("test_case", "", "What test cases to run")
testCase = flag.String("test_case", "", "What test cases to run")

// The rest of these are unused, but present to fulfill the client interface
serverHostOverride = flag.String("server_host_override", "", "Unused")
Expand Down Expand Up @@ -86,33 +85,50 @@ func TestUnknownFrameType(t *testing.T) {
}

func TestTLSApplicationProtocol(t *testing.T) {
if *testCase != "tls" {
return
}
ctx := InteropCtx(t)
err := testTLSApplicationProtocol(ctx);
err := testTLSApplicationProtocol(ctx)
matchError(t, err, "EOF")
}

func TestTLSMaxVersion(t *testing.T) {
if *testCase != "tls" {
return
}
ctx := InteropCtx(t)
err := testTLSMaxVersion(ctx, tls.VersionTLS11);
err := testTLSMaxVersion(ctx, tls.VersionTLS11)
// TODO(carl-mastrangelo): maybe this should be some other error. If the server picks
// the wrong protocol version, thats bad too.
matchError(t, err, "EOF", "server selected unsupported protocol")
}

func TestTLSBadCipherSuites(t *testing.T) {
if *testCase != "tls" {
return
}
ctx := InteropCtx(t)
err := testTLSBadCipherSuites(ctx)
matchError(t, err, "EOF", "Got goaway frame")
}

func TestClientPrefaceWithStreamId(t *testing.T) {
ctx := InteropCtx(t)
err := testClientPrefaceWithStreamId(ctx)
matchError(t, err, "EOF")
}

func matchError(t *testing.T, err error, matches ... string) {
if err == nil {
t.Fatal("Expected an error")
}
for _, s := range matches {
if strings.Contains(err.Error(), s) {
return
}
}
t.Fatalf("Error %v not in %+v", err, matches)
func matchError(t *testing.T, err error, matches ...string) {
if err == nil {
t.Fatal("Expected an error")
}
for _, s := range matches {
if strings.Contains(err.Error(), s) {
return
}
}
t.Fatalf("Error %v not in %+v", err, matches)
}

func TestMain(m *testing.M) {
Expand Down

0 comments on commit 8a1cdec

Please sign in to comment.