@@ -48,6 +48,103 @@ 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 ' ]['protocol ' ]));
77
+
78
+ if ($ meta ['crypto ' ]['protocol ' ] === 'UNKNOWN ' ) {
79
+ // TLSv1.3 protocol will only be added via https://github.com/php/php-src/pull/3700
80
+ // prior to merging that PR, this info is still available in the cipher version by OpenSSL
81
+ $ this ->assertTrue (isset ($ meta ['crypto ' ]['cipher_version ' ]));
82
+ $ this ->assertEquals ('TLSv1.3 ' , $ meta ['crypto ' ]['cipher_version ' ]);
83
+ } else {
84
+ $ this ->assertEquals ('TLSv1.3 ' , $ meta ['crypto ' ]['protocol ' ]);
85
+ }
86
+ }
87
+
88
+ public function testClientUsesTls12WhenCryptoMethodIsExplicitlyConfiguredByClient ()
89
+ {
90
+ if (PHP_VERSION_ID < 70000 ) {
91
+ $ this ->markTestSkipped ('Test requires PHP 7+ for crypto meta data ' );
92
+ }
93
+
94
+ $ loop = Factory::create ();
95
+
96
+ $ server = new TcpServer (0 , $ loop );
97
+ $ server = new SecureServer ($ server , $ loop , array (
98
+ 'local_cert ' => __DIR__ . '/../examples/localhost.pem '
99
+ ));
100
+
101
+ $ connector = new SecureConnector (new TcpConnector ($ loop ), $ loop , array (
102
+ 'verify_peer ' => false ,
103
+ 'crypto_method ' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
104
+ ));
105
+ $ promise = $ connector ->connect ($ server ->getAddress ());
106
+
107
+ /* @var ConnectionInterface $client */
108
+ $ client = Block \await ($ promise , $ loop , self ::TIMEOUT );
109
+
110
+ $ this ->assertInstanceOf ('React\Socket\Connection ' , $ client );
111
+ $ this ->assertTrue (isset ($ client ->stream ));
112
+
113
+ $ meta = stream_get_meta_data ($ client ->stream );
114
+ $ this ->assertTrue (isset ($ meta ['crypto ' ]['protocol ' ]));
115
+ $ this ->assertEquals ('TLSv1.2 ' , $ meta ['crypto ' ]['protocol ' ]);
116
+ }
117
+
118
+ public function testClientUsesTls12WhenCryptoMethodIsExplicitlyConfiguredByServer ()
119
+ {
120
+ if (PHP_VERSION_ID < 70000 ) {
121
+ $ this ->markTestSkipped ('Test requires PHP 7+ for crypto meta data ' );
122
+ }
123
+
124
+ $ loop = Factory::create ();
125
+
126
+ $ server = new TcpServer (0 , $ loop );
127
+ $ server = new SecureServer ($ server , $ loop , array (
128
+ 'local_cert ' => __DIR__ . '/../examples/localhost.pem ' ,
129
+ 'crypto_method ' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
130
+ ));
131
+
132
+ $ connector = new SecureConnector (new TcpConnector ($ loop ), $ loop , array (
133
+ 'verify_peer ' => false
134
+ ));
135
+ $ promise = $ connector ->connect ($ server ->getAddress ());
136
+
137
+ /* @var ConnectionInterface $client */
138
+ $ client = Block \await ($ promise , $ loop , self ::TIMEOUT );
139
+
140
+ $ this ->assertInstanceOf ('React\Socket\Connection ' , $ client );
141
+ $ this ->assertTrue (isset ($ client ->stream ));
142
+
143
+ $ meta = stream_get_meta_data ($ client ->stream );
144
+ $ this ->assertTrue (isset ($ meta ['crypto ' ]['protocol ' ]));
145
+ $ this ->assertEquals ('TLSv1.2 ' , $ meta ['crypto ' ]['protocol ' ]);
146
+ }
147
+
51
148
public function testServerEmitsConnectionForClientConnection ()
52
149
{
53
150
$ loop = Factory::create ();
@@ -621,4 +718,21 @@ private function createPromiseForEvent(EventEmitterInterface $emitter, $event, $
621
718
});
622
719
});
623
720
}
721
+
722
+ private function supportsTls13 ()
723
+ {
724
+ // TLS 1.3 is supported as of OpenSSL 1.1.1 (https://www.openssl.org/blog/blog/2018/09/11/release111/)
725
+ // The OpenSSL library version can only be obtained by parsing output from phpinfo().
726
+ // OPENSSL_VERSION_TEXT refers to header version which does not necessarily match actual library version
727
+ // see php -i | grep OpenSSL
728
+ // OpenSSL Library Version => OpenSSL 1.1.1 11 Sep 2018
729
+ ob_start ();
730
+ phpinfo (INFO_MODULES );
731
+ $ info = ob_get_clean ();
732
+
733
+ if (preg_match ('/OpenSSL Library Version => OpenSSL (\S+)/ ' , $ info , $ match )) {
734
+ return version_compare ($ match [1 ], '1.1.1 ' , '>= ' );
735
+ }
736
+ return false ;
737
+ }
624
738
}
0 commit comments