|
|
@@ -115,6 +115,9 @@ type testCase struct { |
|
|
|
// expectedVersion, if non-zero, specifies the TLS version that must be |
|
|
|
// negotiated. |
|
|
|
expectedVersion uint16 |
|
|
|
// expectedResumeVersion, if non-zero, specifies the TLS version that |
|
|
|
// must be negotiated on resumption. If zero, expectedVersion is used. |
|
|
|
expectedResumeVersion uint16 |
|
|
|
// expectChannelID controls whether the connection should have |
|
|
|
// negotiated a Channel ID with channelIDKey. |
|
|
|
expectChannelID bool |
|
|
@@ -132,8 +135,13 @@ type testCase struct { |
|
|
|
// keyFile is the path to the private key to use for the server. |
|
|
|
keyFile string |
|
|
|
// resumeSession controls whether a second connection should be tested |
|
|
|
// which resumes the first session. |
|
|
|
// which attempts to resume the first session. |
|
|
|
resumeSession bool |
|
|
|
// resumeConfig, if not nil, points to a Config to be used on |
|
|
|
// resumption. SessionTicketKey and ClientSessionCache are copied from |
|
|
|
// the initial connection's config. If nil, the initial connection's |
|
|
|
// config is used. |
|
|
|
resumeConfig *Config |
|
|
|
// sendPrefix sends a prefix on the socket before actually performing a |
|
|
|
// handshake. |
|
|
|
sendPrefix string |
|
|
@@ -478,7 +486,7 @@ var testCases = []testCase{ |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) error { |
|
|
|
func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error { |
|
|
|
if test.protocol == dtls { |
|
|
|
conn = newPacketAdaptor(conn) |
|
|
|
} |
|
|
@@ -509,8 +517,15 @@ func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) e |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
if vers := tlsConn.ConnectionState().Version; test.expectedVersion != 0 && vers != test.expectedVersion { |
|
|
|
return fmt.Errorf("got version %x, expected %x", vers, test.expectedVersion) |
|
|
|
// TODO(davidben): move all per-connection expectations into a dedicated |
|
|
|
// expectations struct that can be specified separately for the two |
|
|
|
// legs. |
|
|
|
expectedVersion := test.expectedVersion |
|
|
|
if isResume && test.expectedResumeVersion != 0 { |
|
|
|
expectedVersion = test.expectedResumeVersion |
|
|
|
} |
|
|
|
if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion { |
|
|
|
return fmt.Errorf("got version %x, expected %x", vers, expectedVersion) |
|
|
|
} |
|
|
|
|
|
|
|
if test.expectChannelID { |
|
|
@@ -698,10 +713,23 @@ func runTest(test *testCase, buildDir string) error { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
err := doExchange(test, &config, conn, test.messageLen) |
|
|
|
err := doExchange(test, &config, conn, test.messageLen, |
|
|
|
false /* not a resumption */) |
|
|
|
conn.Close() |
|
|
|
if err == nil && test.resumeSession { |
|
|
|
err = doExchange(test, &config, connResume, test.messageLen) |
|
|
|
var resumeConfig Config |
|
|
|
if test.resumeConfig != nil { |
|
|
|
resumeConfig = *test.resumeConfig |
|
|
|
if len(resumeConfig.Certificates) == 0 { |
|
|
|
resumeConfig.Certificates = []Certificate{getRSACertificate()} |
|
|
|
} |
|
|
|
resumeConfig.SessionTicketKey = config.SessionTicketKey |
|
|
|
resumeConfig.ClientSessionCache = config.ClientSessionCache |
|
|
|
} else { |
|
|
|
resumeConfig = config |
|
|
|
} |
|
|
|
err = doExchange(test, &resumeConfig, connResume, test.messageLen, |
|
|
|
true /* resumption */) |
|
|
|
} |
|
|
|
connResume.Close() |
|
|
|
|
|
|
@@ -1516,6 +1544,68 @@ func addExtensionTests() { |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
func addResumptionVersionTests() { |
|
|
|
// TODO(davidben): Once DTLS 1.2 is working, test that as well. |
|
|
|
for _, sessionVers := range tlsVersions { |
|
|
|
// TODO(davidben): SSLv3 is omitted here because runner does not |
|
|
|
// support resumption with session IDs. |
|
|
|
if sessionVers.version == VersionSSL30 { |
|
|
|
continue |
|
|
|
} |
|
|
|
for _, resumeVers := range tlsVersions { |
|
|
|
if resumeVers.version == VersionSSL30 { |
|
|
|
continue |
|
|
|
} |
|
|
|
suffix := "-" + sessionVers.name + "-" + resumeVers.name |
|
|
|
|
|
|
|
// TODO(davidben): Write equivalent tests for the server |
|
|
|
// and clean up the server's logic. This requires being |
|
|
|
// able to give the shim a different set of SSL_OP_NO_* |
|
|
|
// flags between the initial connection and the |
|
|
|
// resume. Perhaps resumption should be tested by |
|
|
|
// serializing the SSL_SESSION and starting a second |
|
|
|
// shim. |
|
|
|
testCases = append(testCases, testCase{ |
|
|
|
name: "Resume-Client" + suffix, |
|
|
|
resumeSession: true, |
|
|
|
config: Config{ |
|
|
|
MaxVersion: sessionVers.version, |
|
|
|
CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, |
|
|
|
Bugs: ProtocolBugs{ |
|
|
|
AllowSessionVersionMismatch: true, |
|
|
|
}, |
|
|
|
}, |
|
|
|
expectedVersion: sessionVers.version, |
|
|
|
resumeConfig: &Config{ |
|
|
|
MaxVersion: resumeVers.version, |
|
|
|
CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, |
|
|
|
Bugs: ProtocolBugs{ |
|
|
|
AllowSessionVersionMismatch: true, |
|
|
|
}, |
|
|
|
}, |
|
|
|
expectedResumeVersion: resumeVers.version, |
|
|
|
}) |
|
|
|
|
|
|
|
testCases = append(testCases, testCase{ |
|
|
|
name: "Resume-Client-NoResume" + suffix, |
|
|
|
flags: []string{"-expect-session-miss"}, |
|
|
|
resumeSession: true, |
|
|
|
config: Config{ |
|
|
|
MaxVersion: sessionVers.version, |
|
|
|
CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, |
|
|
|
}, |
|
|
|
expectedVersion: sessionVers.version, |
|
|
|
resumeConfig: &Config{ |
|
|
|
MaxVersion: resumeVers.version, |
|
|
|
CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, |
|
|
|
SessionTicketsDisabled: true, |
|
|
|
}, |
|
|
|
expectedResumeVersion: resumeVers.version, |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) { |
|
|
|
defer wg.Done() |
|
|
|
|
|
|
@@ -1570,6 +1660,7 @@ func main() { |
|
|
|
addVersionNegotiationTests() |
|
|
|
addD5BugTests() |
|
|
|
addExtensionTests() |
|
|
|
addResumptionVersionTests() |
|
|
|
for _, async := range []bool{false, true} { |
|
|
|
for _, splitHandshake := range []bool{false, true} { |
|
|
|
for _, protocol := range []protocol{tls, dtls} { |
|
|
|