Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

Commit 219c9ad

Browse files
committed
Merge branch 'hotfix/zf2-490'
2 parents 3025666 + 7befdef commit 219c9ad

File tree

2 files changed

+97
-32
lines changed

2 files changed

+97
-32
lines changed

src/Client/Adapter/Socket.php

Lines changed: 87 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@
2727
*/
2828
class Socket implements HttpAdapter, StreamInterface
2929
{
30+
/**
31+
* Map SSL transport wrappers to stream crypto method constants
32+
*
33+
* @var array
34+
*/
35+
protected static $sslCryptoTypes = array(
36+
'ssl' => STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
37+
'sslv2' => STREAM_CRYPTO_METHOD_SSLv2_CLIENT,
38+
'sslv3' => STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
39+
'tls' => STREAM_CRYPTO_METHOD_TLS_CLIENT
40+
);
41+
3042
/**
3143
* The socket for server connection
3244
*
@@ -174,50 +186,53 @@ public function getStreamContext()
174186
*/
175187
public function connect($host, $port = 80, $secure = false)
176188
{
177-
// If the URI should be accessed via SSL, prepend the Hostname with ssl://
178-
$host = ($secure ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
179-
180189
// If we are connected to the wrong host, disconnect first
181190
if (($this->connected_to[0] != $host || $this->connected_to[1] != $port)) {
182-
if (is_resource($this->socket)) $this->close();
191+
if (is_resource($this->socket)) {
192+
$this->close();
193+
}
183194
}
184195

185196
// Now, if we are not connected, connect
186-
if (! is_resource($this->socket) || ! $this->config['keepalive']) {
197+
if (!is_resource($this->socket) || ! $this->config['keepalive']) {
187198
$context = $this->getStreamContext();
199+
188200
if ($secure || $this->config['sslusecontext']) {
189201
if ($this->config['sslverifypeer'] !== null) {
190-
if (! stream_context_set_option($context, 'ssl', 'verify_peer',
191-
$this->config['sslverifypeer'])) {
202+
if (!stream_context_set_option($context, 'ssl', 'verify_peer', $this->config['sslverifypeer'])) {
192203
throw new AdapterException\RuntimeException('Unable to set sslverifypeer option');
193204
}
194-
if (! stream_context_set_option($context, 'ssl', 'capath',
195-
$this->config['sslcapath'])) {
205+
}
206+
207+
if ($this->config['sslcapath']) {
208+
if (!stream_context_set_option($context, 'ssl', 'capath', $this->config['sslcapath'])) {
196209
throw new AdapterException\RuntimeException('Unable to set sslcapath option');
197210
}
198-
if ($this->config['sslallowselfsigned'] !== null) {
199-
if (! stream_context_set_option($context, 'ssl', 'allow_self_signed',
200-
$this->config['sslallowselfsigned'])) {
201-
throw new AdapterException\RuntimeException('Unable to set sslallowselfsigned option');
202-
}
211+
}
212+
213+
if ($this->config['sslallowselfsigned'] !== null) {
214+
if (!stream_context_set_option($context, 'ssl', 'allow_self_signed', $this->config['sslallowselfsigned'])) {
215+
throw new AdapterException\RuntimeException('Unable to set sslallowselfsigned option');
203216
}
204217
}
218+
205219
if ($this->config['sslcert'] !== null) {
206-
if (! stream_context_set_option($context, 'ssl', 'local_cert',
207-
$this->config['sslcert'])) {
220+
if (!stream_context_set_option($context, 'ssl', 'local_cert', $this->config['sslcert'])) {
208221
throw new AdapterException\RuntimeException('Unable to set sslcert option');
209222
}
210223
}
224+
211225
if ($this->config['sslpassphrase'] !== null) {
212-
if (! stream_context_set_option($context, 'ssl', 'passphrase',
213-
$this->config['sslpassphrase'])) {
226+
if (!stream_context_set_option($context, 'ssl', 'passphrase', $this->config['sslpassphrase'])) {
214227
throw new AdapterException\RuntimeException('Unable to set sslpassphrase option');
215228
}
216229
}
217230
}
218231

219232
$flags = STREAM_CLIENT_CONNECT;
220-
if ($this->config['persistent']) $flags |= STREAM_CLIENT_PERSISTENT;
233+
if ($this->config['persistent']) {
234+
$flags |= STREAM_CLIENT_PERSISTENT;
235+
}
221236

222237
ErrorHandler::start();
223238
$this->socket = stream_socket_client(
@@ -230,21 +245,66 @@ public function connect($host, $port = 80, $secure = false)
230245
);
231246
$error = ErrorHandler::stop();
232247

233-
if (! $this->socket) {
248+
if (!$this->socket) {
234249
$this->close();
235-
throw new AdapterException\RuntimeException(sprintf(
236-
'Unable to connect to %s:%d%s',
237-
$host,
238-
$port,
239-
($error ? '. Error #' . $error->getCode() . ': ' . $error->getMessage() : '')
240-
), 0, $error);
250+
throw new AdapterException\RuntimeException(
251+
sprintf(
252+
'Unable to connect to %s:%d%s',
253+
$host,
254+
$port,
255+
($error ? '. Error #' . $error->getCode() . ': ' . $error->getMessage() : '')
256+
),
257+
0,
258+
$error
259+
);
241260
}
242261

243262
// Set the stream timeout
244-
if (! stream_set_timeout($this->socket, (int) $this->config['timeout'])) {
263+
if (!stream_set_timeout($this->socket, (int) $this->config['timeout'])) {
245264
throw new AdapterException\RuntimeException('Unable to set the connection timeout');
246265
}
247266

267+
if ($secure || $this->config['sslusecontext']) {
268+
if ($this->config['ssltransport'] && isset(self::$sslCryptoTypes[$this->config['ssltransport']])) {
269+
$sslCryptoMethod = self::$sslCryptoTypes[$this->config['ssltransport']];
270+
} else {
271+
$sslCryptoMethod = STREAM_CRYPTO_METHOD_SSLv23_CLIENT;
272+
}
273+
274+
ErrorHandler::start();
275+
$test = stream_socket_enable_crypto($this->socket, true, $sslCryptoMethod);
276+
$error = ErrorHandler::stop();
277+
if (!$test || $error) {
278+
// Error handling is kind of difficult when it comes to SSL
279+
$errorString = '';
280+
while (($sslError = openssl_error_string()) != false) {
281+
$errorString .= "; SSL error: $sslError";
282+
}
283+
$this->close();
284+
285+
if ((! $errorString) && $this->config['sslverifypeer']) {
286+
// There's good chance our error is due to sslcapath not being properly set
287+
if (! ($this->config['sslcapath'] && is_dir($this->config['sslcapath']))) {
288+
$errorString = 'make sure the "sslcapath" option points to a valid SSL certificate directory';
289+
}
290+
}
291+
292+
if ($errorString) {
293+
$errorString = ": $errorString";
294+
}
295+
296+
throw new AdapterException\RuntimeException(sprintf(
297+
'Unable to enable crypto on TCP connection %s%s',
298+
$host,
299+
$errorString
300+
), 0, $error);
301+
}
302+
303+
$host = $this->config['ssltransport'] . "://" . $host;
304+
} else {
305+
$host = 'tcp://' . $host;
306+
}
307+
248308
// Update connected_to
249309
$this->connected_to = array($host, $port);
250310
}

test/Client/SocketTest.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,15 +130,17 @@ public function testSetConfigInvalidConfig($config)
130130

131131
public function testGetNewStreamContext()
132132
{
133-
$adapter = new $this->config['adapter'];
133+
$adapterClass = $this->config['adapter'];
134+
$adapter = new $adapterClass;
134135
$context = $adapter->getStreamContext();
135136

136137
$this->assertEquals('stream-context', get_resource_type($context));
137138
}
138139

139140
public function testSetNewStreamContextResource()
140141
{
141-
$adapter = new $this->config['adapter'];
142+
$adapterClass = $this->config['adapter'];
143+
$adapter = new $adapterClass;
142144
$context = stream_context_create();
143145

144146
$adapter->setStreamContext($context);
@@ -148,7 +150,8 @@ public function testSetNewStreamContextResource()
148150

149151
public function testSetNewStreamContextOptions()
150152
{
151-
$adapter = new $this->config['adapter'];
153+
$adapterClass = $this->config['adapter'];
154+
$adapter = new $adapterClass;
152155
$options = array(
153156
'socket' => array(
154157
'bindto' => '1.2.3.4:0'
@@ -176,7 +179,8 @@ public function testSetInvalidContextOptions($invalid)
176179
'Zend\Http\Client\Adapter\Exception\InvalidArgumentException',
177180
'Expecting either a stream context resource or array');
178181

179-
$adapter = new $this->config['adapter'];
182+
$adapterClass = $this->config['adapter'];
183+
$adapter = new $adapterClass;
180184
$adapter->setStreamContext($invalid);
181185
}
182186

@@ -186,7 +190,8 @@ public function testSetHttpsStreamContextParam()
186190
$this->markTestSkipped();
187191
}
188192

189-
$adapter = new $this->config['adapter'];
193+
$adapterClass = $this->config['adapter'];
194+
$adapter = new $adapterClass;
190195
$adapter->setStreamContext(array(
191196
'ssl' => array(
192197
'capture_peer_cert' => true,

0 commit comments

Comments
 (0)