Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

510 righe
14 KiB

  1. // Copyright 2010 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. package tls
  5. import (
  6. "bytes"
  7. "crypto/ecdsa"
  8. "crypto/rsa"
  9. "crypto/x509"
  10. "encoding/pem"
  11. "fmt"
  12. "io"
  13. "net"
  14. "os"
  15. "os/exec"
  16. "path/filepath"
  17. "strconv"
  18. "testing"
  19. "time"
  20. )
  21. // Note: see comment in handshake_test.go for details of how the reference
  22. // tests work.
  23. // blockingSource is an io.Reader that blocks a Read call until it's closed.
  24. type blockingSource chan bool
  25. func (b blockingSource) Read([]byte) (n int, err error) {
  26. <-b
  27. return 0, io.EOF
  28. }
  29. // clientTest represents a test of the TLS client handshake against a reference
  30. // implementation.
  31. type clientTest struct {
  32. // name is a freeform string identifying the test and the file in which
  33. // the expected results will be stored.
  34. name string
  35. // command, if not empty, contains a series of arguments for the
  36. // command to run for the reference server.
  37. command []string
  38. // config, if not nil, contains a custom Config to use for this test.
  39. config *Config
  40. // cert, if not empty, contains a DER-encoded certificate for the
  41. // reference server.
  42. cert []byte
  43. // key, if not nil, contains either a *rsa.PrivateKey or
  44. // *ecdsa.PrivateKey which is the private key for the reference server.
  45. key interface{}
  46. // validate, if not nil, is a function that will be called with the
  47. // ConnectionState of the resulting connection. It returns a non-nil
  48. // error if the ConnectionState is unacceptable.
  49. validate func(ConnectionState) error
  50. }
  51. var defaultServerCommand = []string{"openssl", "s_server"}
  52. // connFromCommand starts the reference server process, connects to it and
  53. // returns a recordingConn for the connection. The stdin return value is a
  54. // blockingSource for the stdin of the child process. It must be closed before
  55. // Waiting for child.
  56. func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, stdin blockingSource, err error) {
  57. cert := testRSACertificate
  58. if len(test.cert) > 0 {
  59. cert = test.cert
  60. }
  61. certPath := tempFile(string(cert))
  62. defer os.Remove(certPath)
  63. var key interface{} = testRSAPrivateKey
  64. if test.key != nil {
  65. key = test.key
  66. }
  67. var pemType string
  68. var derBytes []byte
  69. switch key := key.(type) {
  70. case *rsa.PrivateKey:
  71. pemType = "RSA"
  72. derBytes = x509.MarshalPKCS1PrivateKey(key)
  73. case *ecdsa.PrivateKey:
  74. pemType = "EC"
  75. var err error
  76. derBytes, err = x509.MarshalECPrivateKey(key)
  77. if err != nil {
  78. panic(err)
  79. }
  80. default:
  81. panic("unknown key type")
  82. }
  83. var pemOut bytes.Buffer
  84. pem.Encode(&pemOut, &pem.Block{Type: pemType + " PRIVATE KEY", Bytes: derBytes})
  85. keyPath := tempFile(string(pemOut.Bytes()))
  86. defer os.Remove(keyPath)
  87. var command []string
  88. if len(test.command) > 0 {
  89. command = append(command, test.command...)
  90. } else {
  91. command = append(command, defaultServerCommand...)
  92. }
  93. command = append(command, "-cert", certPath, "-certform", "DER", "-key", keyPath)
  94. // serverPort contains the port that OpenSSL will listen on. OpenSSL
  95. // can't take "0" as an argument here so we have to pick a number and
  96. // hope that it's not in use on the machine. Since this only occurs
  97. // when -update is given and thus when there's a human watching the
  98. // test, this isn't too bad.
  99. const serverPort = 24323
  100. command = append(command, "-accept", strconv.Itoa(serverPort))
  101. cmd := exec.Command(command[0], command[1:]...)
  102. stdin = blockingSource(make(chan bool))
  103. cmd.Stdin = stdin
  104. var out bytes.Buffer
  105. cmd.Stdout = &out
  106. cmd.Stderr = &out
  107. if err := cmd.Start(); err != nil {
  108. return nil, nil, nil, err
  109. }
  110. // OpenSSL does print an "ACCEPT" banner, but it does so *before*
  111. // opening the listening socket, so we can't use that to wait until it
  112. // has started listening. Thus we are forced to poll until we get a
  113. // connection.
  114. var tcpConn net.Conn
  115. for i := uint(0); i < 5; i++ {
  116. tcpConn, err = net.DialTCP("tcp", nil, &net.TCPAddr{
  117. IP: net.IPv4(127, 0, 0, 1),
  118. Port: serverPort,
  119. })
  120. if err == nil {
  121. break
  122. }
  123. time.Sleep((1 << i) * 5 * time.Millisecond)
  124. }
  125. if err != nil {
  126. close(stdin)
  127. out.WriteTo(os.Stdout)
  128. cmd.Process.Kill()
  129. return nil, nil, nil, cmd.Wait()
  130. }
  131. record := &recordingConn{
  132. Conn: tcpConn,
  133. }
  134. return record, cmd, stdin, nil
  135. }
  136. func (test *clientTest) dataPath() string {
  137. return filepath.Join("testdata", "Client-"+test.name)
  138. }
  139. func (test *clientTest) loadData() (flows [][]byte, err error) {
  140. in, err := os.Open(test.dataPath())
  141. if err != nil {
  142. return nil, err
  143. }
  144. defer in.Close()
  145. return parseTestData(in)
  146. }
  147. func (test *clientTest) run(t *testing.T, write bool) {
  148. var clientConn, serverConn net.Conn
  149. var recordingConn *recordingConn
  150. var childProcess *exec.Cmd
  151. var stdin blockingSource
  152. if write {
  153. var err error
  154. recordingConn, childProcess, stdin, err = test.connFromCommand()
  155. if err != nil {
  156. t.Fatalf("Failed to start subcommand: %s", err)
  157. }
  158. clientConn = recordingConn
  159. } else {
  160. clientConn, serverConn = net.Pipe()
  161. }
  162. config := test.config
  163. if config == nil {
  164. config = testConfig
  165. }
  166. client := Client(clientConn, config)
  167. doneChan := make(chan bool)
  168. go func() {
  169. if _, err := client.Write([]byte("hello\n")); err != nil {
  170. t.Errorf("Client.Write failed: %s", err)
  171. }
  172. if test.validate != nil {
  173. if err := test.validate(client.ConnectionState()); err != nil {
  174. t.Logf("validate callback returned error: %s", err)
  175. }
  176. }
  177. client.Close()
  178. clientConn.Close()
  179. doneChan <- true
  180. }()
  181. if !write {
  182. flows, err := test.loadData()
  183. if err != nil {
  184. t.Fatalf("%s: failed to load data from %s: %v", test.name, test.dataPath(), err)
  185. }
  186. for i, b := range flows {
  187. if i%2 == 1 {
  188. serverConn.Write(b)
  189. continue
  190. }
  191. bb := make([]byte, len(b))
  192. _, err := io.ReadFull(serverConn, bb)
  193. if err != nil {
  194. t.Fatalf("%s #%d: %s", test.name, i, err)
  195. }
  196. if !bytes.Equal(b, bb) {
  197. t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", test.name, i, bb, b)
  198. }
  199. }
  200. serverConn.Close()
  201. }
  202. <-doneChan
  203. if write {
  204. path := test.dataPath()
  205. out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
  206. if err != nil {
  207. t.Fatalf("Failed to create output file: %s", err)
  208. }
  209. defer out.Close()
  210. recordingConn.Close()
  211. close(stdin)
  212. childProcess.Process.Kill()
  213. childProcess.Wait()
  214. if len(recordingConn.flows) < 3 {
  215. childProcess.Stdout.(*bytes.Buffer).WriteTo(os.Stdout)
  216. t.Fatalf("Client connection didn't work")
  217. }
  218. recordingConn.WriteTo(out)
  219. fmt.Printf("Wrote %s\n", path)
  220. }
  221. }
  222. func runClientTestForVersion(t *testing.T, template *clientTest, prefix, option string) {
  223. test := *template
  224. test.name = prefix + test.name
  225. if len(test.command) == 0 {
  226. test.command = defaultClientCommand
  227. }
  228. test.command = append([]string(nil), test.command...)
  229. test.command = append(test.command, option)
  230. test.run(t, *update)
  231. }
  232. func runClientTestTLS10(t *testing.T, template *clientTest) {
  233. runClientTestForVersion(t, template, "TLSv10-", "-tls1")
  234. }
  235. func runClientTestTLS11(t *testing.T, template *clientTest) {
  236. runClientTestForVersion(t, template, "TLSv11-", "-tls1_1")
  237. }
  238. func runClientTestTLS12(t *testing.T, template *clientTest) {
  239. runClientTestForVersion(t, template, "TLSv12-", "-tls1_2")
  240. }
  241. func TestHandshakeClientRSARC4(t *testing.T) {
  242. test := &clientTest{
  243. name: "RSA-RC4",
  244. command: []string{"openssl", "s_server", "-cipher", "RC4-SHA"},
  245. }
  246. runClientTestTLS10(t, test)
  247. runClientTestTLS11(t, test)
  248. runClientTestTLS12(t, test)
  249. }
  250. func TestHandshakeClientECDHERSAAES(t *testing.T) {
  251. test := &clientTest{
  252. name: "ECDHE-RSA-AES",
  253. command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES128-SHA"},
  254. }
  255. runClientTestTLS10(t, test)
  256. runClientTestTLS11(t, test)
  257. runClientTestTLS12(t, test)
  258. }
  259. func TestHandshakeClientECDHEECDSAAES(t *testing.T) {
  260. test := &clientTest{
  261. name: "ECDHE-ECDSA-AES",
  262. command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA"},
  263. cert: testECDSACertificate,
  264. key: testECDSAPrivateKey,
  265. }
  266. runClientTestTLS10(t, test)
  267. runClientTestTLS11(t, test)
  268. runClientTestTLS12(t, test)
  269. }
  270. func TestHandshakeClientECDHEECDSAAESGCM(t *testing.T) {
  271. test := &clientTest{
  272. name: "ECDHE-ECDSA-AES-GCM",
  273. command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-GCM-SHA256"},
  274. cert: testECDSACertificate,
  275. key: testECDSAPrivateKey,
  276. }
  277. runClientTestTLS12(t, test)
  278. }
  279. func TestHandshakeClientAES256GCMSHA384(t *testing.T) {
  280. test := &clientTest{
  281. name: "ECDHE-ECDSA-AES256-GCM-SHA384",
  282. command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES256-GCM-SHA384"},
  283. cert: testECDSACertificate,
  284. key: testECDSAPrivateKey,
  285. }
  286. runClientTestTLS12(t, test)
  287. }
  288. func TestHandshakeClientCertRSA(t *testing.T) {
  289. config := *testConfig
  290. cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM))
  291. config.Certificates = []Certificate{cert}
  292. test := &clientTest{
  293. name: "ClientCert-RSA-RSA",
  294. command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
  295. config: &config,
  296. }
  297. runClientTestTLS10(t, test)
  298. runClientTestTLS12(t, test)
  299. test = &clientTest{
  300. name: "ClientCert-RSA-ECDSA",
  301. command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"},
  302. config: &config,
  303. cert: testECDSACertificate,
  304. key: testECDSAPrivateKey,
  305. }
  306. runClientTestTLS10(t, test)
  307. runClientTestTLS12(t, test)
  308. test = &clientTest{
  309. name: "ClientCert-RSA-AES256-GCM-SHA384",
  310. command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES256-GCM-SHA384", "-verify", "1"},
  311. config: &config,
  312. cert: testRSACertificate,
  313. key: testRSAPrivateKey,
  314. }
  315. runClientTestTLS12(t, test)
  316. }
  317. func TestHandshakeClientCertECDSA(t *testing.T) {
  318. config := *testConfig
  319. cert, _ := X509KeyPair([]byte(clientECDSACertificatePEM), []byte(clientECDSAKeyPEM))
  320. config.Certificates = []Certificate{cert}
  321. test := &clientTest{
  322. name: "ClientCert-ECDSA-RSA",
  323. command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
  324. config: &config,
  325. }
  326. runClientTestTLS10(t, test)
  327. runClientTestTLS12(t, test)
  328. test = &clientTest{
  329. name: "ClientCert-ECDSA-ECDSA",
  330. command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"},
  331. config: &config,
  332. cert: testECDSACertificate,
  333. key: testECDSAPrivateKey,
  334. }
  335. runClientTestTLS10(t, test)
  336. runClientTestTLS12(t, test)
  337. }
  338. func TestClientResumption(t *testing.T) {
  339. serverConfig := &Config{
  340. CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
  341. Certificates: testConfig.Certificates,
  342. }
  343. clientConfig := &Config{
  344. CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
  345. InsecureSkipVerify: true,
  346. ClientSessionCache: NewLRUClientSessionCache(32),
  347. }
  348. testResumeState := func(test string, didResume bool) {
  349. hs, err := testHandshake(clientConfig, serverConfig)
  350. if err != nil {
  351. t.Fatalf("%s: handshake failed: %s", test, err)
  352. }
  353. if hs.DidResume != didResume {
  354. t.Fatalf("%s resumed: %v, expected: %v", test, hs.DidResume, didResume)
  355. }
  356. }
  357. testResumeState("Handshake", false)
  358. testResumeState("Resume", true)
  359. if _, err := io.ReadFull(serverConfig.rand(), serverConfig.SessionTicketKey[:]); err != nil {
  360. t.Fatalf("Failed to invalidate SessionTicketKey")
  361. }
  362. testResumeState("InvalidSessionTicketKey", false)
  363. testResumeState("ResumeAfterInvalidSessionTicketKey", true)
  364. clientConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA}
  365. testResumeState("DifferentCipherSuite", false)
  366. testResumeState("DifferentCipherSuiteRecovers", true)
  367. clientConfig.ClientSessionCache = nil
  368. testResumeState("WithoutSessionCache", false)
  369. }
  370. func TestLRUClientSessionCache(t *testing.T) {
  371. // Initialize cache of capacity 4.
  372. cache := NewLRUClientSessionCache(4)
  373. cs := make([]ClientSessionState, 6)
  374. keys := []string{"0", "1", "2", "3", "4", "5", "6"}
  375. // Add 4 entries to the cache and look them up.
  376. for i := 0; i < 4; i++ {
  377. cache.Put(keys[i], &cs[i])
  378. }
  379. for i := 0; i < 4; i++ {
  380. if s, ok := cache.Get(keys[i]); !ok || s != &cs[i] {
  381. t.Fatalf("session cache failed lookup for added key: %s", keys[i])
  382. }
  383. }
  384. // Add 2 more entries to the cache. First 2 should be evicted.
  385. for i := 4; i < 6; i++ {
  386. cache.Put(keys[i], &cs[i])
  387. }
  388. for i := 0; i < 2; i++ {
  389. if s, ok := cache.Get(keys[i]); ok || s != nil {
  390. t.Fatalf("session cache should have evicted key: %s", keys[i])
  391. }
  392. }
  393. // Touch entry 2. LRU should evict 3 next.
  394. cache.Get(keys[2])
  395. cache.Put(keys[0], &cs[0])
  396. if s, ok := cache.Get(keys[3]); ok || s != nil {
  397. t.Fatalf("session cache should have evicted key 3")
  398. }
  399. // Update entry 0 in place.
  400. cache.Put(keys[0], &cs[3])
  401. if s, ok := cache.Get(keys[0]); !ok || s != &cs[3] {
  402. t.Fatalf("session cache failed update for key 0")
  403. }
  404. // Adding a nil entry is valid.
  405. cache.Put(keys[0], nil)
  406. if s, ok := cache.Get(keys[0]); !ok || s != nil {
  407. t.Fatalf("failed to add nil entry to cache")
  408. }
  409. }
  410. func TestHandshakeClientALPNMatch(t *testing.T) {
  411. config := *testConfig
  412. config.NextProtos = []string{"proto2", "proto1"}
  413. test := &clientTest{
  414. name: "ALPN",
  415. // Note that this needs OpenSSL 1.0.2 because that is the first
  416. // version that supports the -alpn flag.
  417. command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"},
  418. config: &config,
  419. validate: func(state ConnectionState) error {
  420. // The server's preferences should override the client.
  421. if state.NegotiatedProtocol != "proto1" {
  422. return fmt.Errorf("Got protocol %q, wanted proto1", state.NegotiatedProtocol)
  423. }
  424. return nil
  425. },
  426. }
  427. runClientTestTLS12(t, test)
  428. }
  429. func TestHandshakeClientALPNNoMatch(t *testing.T) {
  430. config := *testConfig
  431. config.NextProtos = []string{"proto3"}
  432. test := &clientTest{
  433. name: "ALPN-NoMatch",
  434. // Note that this needs OpenSSL 1.0.2 because that is the first
  435. // version that supports the -alpn flag.
  436. command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"},
  437. config: &config,
  438. validate: func(state ConnectionState) error {
  439. // There's no overlap so OpenSSL will not select a protocol.
  440. if state.NegotiatedProtocol != "" {
  441. return fmt.Errorf("Got protocol %q, wanted ''", state.NegotiatedProtocol)
  442. }
  443. return nil
  444. },
  445. }
  446. runClientTestTLS12(t, test)
  447. }