@@ -48,6 +48,95 @@ public function testClientCanConnectToServer()
48
48
$ server ->close ();
49
49
}
50
50
51
+ public function testClientUsesTls13ByDefaultWhenSupportedByOpenSSL ()
52
+ {
53
+ if (PHP_VERSION_ID < 70000 || !$ this ->supportsTls13 ()) {
54
+ $ this ->markTestSkipped ('Test requires PHP 7+ for crypto meta data and OpenSSL 1.1.1+ for TLS 1.3 ' );
55
+ }
56
+
57
+ $ loop = Factory::create ();
58
+
59
+ $ server = new TcpServer (0 , $ loop );
60
+ $ server = new SecureServer ($ server , $ loop , array (
61
+ 'local_cert ' => __DIR__ . '/../examples/localhost.pem '
62
+ ));
63
+
64
+ $ connector = new SecureConnector (new TcpConnector ($ loop ), $ loop , array (
65
+ 'verify_peer ' => false
66
+ ));
67
+ $ promise = $ connector ->connect ($ server ->getAddress ());
68
+
69
+ /* @var ConnectionInterface $client */
70
+ $ client = Block \await ($ promise , $ loop , self ::TIMEOUT );
71
+
72
+ $ this ->assertInstanceOf ('React\Socket\Connection ' , $ client );
73
+ $ this ->assertTrue (isset ($ client ->stream ));
74
+
75
+ $ meta = stream_get_meta_data ($ client ->stream );
76
+ $ this ->assertTrue (isset ($ meta ['crypto ' ]['cipher_version ' ]));
77
+ $ this ->assertEquals ('TLSv1.3 ' , $ meta ['crypto ' ]['cipher_version ' ]);
78
+ }
79
+
80
+ public function testClientUsesTls12WhenCryptoMethodIsExplicitlyConfiguredByClient ()
81
+ {
82
+ if (PHP_VERSION_ID < 70000 ) {
83
+ $ this ->markTestSkipped ('Test requires PHP 7+ for crypto meta data ' );
84
+ }
85
+
86
+ $ loop = Factory::create ();
87
+
88
+ $ server = new TcpServer (0 , $ loop );
89
+ $ server = new SecureServer ($ server , $ loop , array (
90
+ 'local_cert ' => __DIR__ . '/../examples/localhost.pem '
91
+ ));
92
+
93
+ $ connector = new SecureConnector (new TcpConnector ($ loop ), $ loop , array (
94
+ 'verify_peer ' => false ,
95
+ 'crypto_method ' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
96
+ ));
97
+ $ promise = $ connector ->connect ($ server ->getAddress ());
98
+
99
+ /* @var ConnectionInterface $client */
100
+ $ client = Block \await ($ promise , $ loop , self ::TIMEOUT );
101
+
102
+ $ this ->assertInstanceOf ('React\Socket\Connection ' , $ client );
103
+ $ this ->assertTrue (isset ($ client ->stream ));
104
+
105
+ $ meta = stream_get_meta_data ($ client ->stream );
106
+ $ this ->assertTrue (isset ($ meta ['crypto ' ]['cipher_version ' ]));
107
+ $ this ->assertEquals ('TLSv1.2 ' , $ meta ['crypto ' ]['cipher_version ' ]);
108
+ }
109
+
110
+ public function testClientUsesTls12WhenCryptoMethodIsExplicitlyConfiguredByServer ()
111
+ {
112
+ if (PHP_VERSION_ID < 70000 ) {
113
+ $ this ->markTestSkipped ('Test requires PHP 7+ for crypto meta data ' );
114
+ }
115
+
116
+ $ loop = Factory::create ();
117
+
118
+ $ server = new TcpServer (0 , $ loop );
119
+ $ server = new SecureServer ($ server , $ loop , array (
120
+ 'local_cert ' => __DIR__ . '/../examples/localhost.pem ' ,
121
+ 'crypto_method ' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
122
+ ));
123
+
124
+ $ connector = new SecureConnector (new TcpConnector ($ loop ), $ loop , array (
125
+ 'verify_peer ' => false
126
+ ));
127
+ $ promise = $ connector ->connect ($ server ->getAddress ());
128
+
129
+ /* @var ConnectionInterface $client */
130
+ $ client = Block \await ($ promise , $ loop , self ::TIMEOUT );
131
+
132
+ $ this ->assertInstanceOf ('React\Socket\Connection ' , $ client );
133
+ $ this ->assertTrue (isset ($ client ->stream ));
134
+
135
+ $ meta = stream_get_meta_data ($ client ->stream );
136
+ $ this ->assertTrue (isset ($ meta ['crypto ' ]['cipher_version ' ]));
137
+ $ this ->assertEquals ('TLSv1.2 ' , $ meta ['crypto ' ]['cipher_version ' ]);
138
+ }
139
+
51
140
public function testServerEmitsConnectionForClientConnection ()
52
141
{
53
142
$ loop = Factory::create ();
@@ -621,4 +710,21 @@ private function createPromiseForEvent(EventEmitterInterface $emitter, $event, $
621
710
});
622
711
});
623
712
}
713
+
714
+ private function supportsTls13 ()
715
+ {
716
+ // TLS 1.3 is supported as of OpenSSL 1.1.1 (https://www.openssl.org/blog/blog/2018/09/11/release111/)
717
+ // The OpenSSL library version can only be obtained by parsing output from phpinfo().
718
+ // OPENSSL_VERSION_TEXT refers to header version which does not necessarily match actual library version
719
+ // see php -i | grep OpenSSL
720
+ // OpenSSL Library Version => OpenSSL 1.1.1 11 Sep 2018
721
+ ob_start ();
722
+ phpinfo (INFO_MODULES );
723
+ $ info = ob_get_clean ();
724
+
725
+ if (preg_match ('/OpenSSL Library Version => OpenSSL (\S+)/ ' , $ info , $ match )) {
726
+ return version_compare ($ match [1 ], '1.1.1 ' , '>= ' );
727
+ }
728
+ return false ;
729
+ }
624
730
}
0 commit comments