This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Dazzle\Socket; |
||
4 | |||
5 | use Dazzle\Loop\LoopInterface; |
||
6 | use Dazzle\Stream\Stream; |
||
7 | use Dazzle\Throwable\Exception\Logic\InstantiationException; |
||
8 | use Dazzle\Throwable\Exception\Runtime\ExecutionException; |
||
9 | use Dazzle\Throwable\Exception\LogicException; |
||
10 | use Error; |
||
11 | use Exception; |
||
12 | |||
13 | class Socket extends Stream implements SocketInterface |
||
14 | { |
||
15 | /** |
||
16 | * @var string |
||
17 | */ |
||
18 | const TYPE_UNIX = 'unix_socket'; |
||
19 | |||
20 | /** |
||
21 | * @var string |
||
22 | */ |
||
23 | const TYPE_TCP = 'tcp_socket/ssl'; |
||
24 | |||
25 | /** |
||
26 | * @var string |
||
27 | */ |
||
28 | const TYPE_UDP = 'udp_socket'; |
||
29 | |||
30 | /** |
||
31 | * @var string |
||
32 | */ |
||
33 | const TYPE_UNKNOWN = 'Unknown'; |
||
34 | |||
35 | /** |
||
36 | * @var int |
||
37 | */ |
||
38 | const CRYPTO_TYPE_UNKNOWN = 0; |
||
39 | |||
40 | /** |
||
41 | * @var int |
||
42 | */ |
||
43 | const CRYPTO_TYPE_SERVER = 1; |
||
44 | |||
45 | /** |
||
46 | * @var int |
||
47 | */ |
||
48 | const CRYPTO_TYPE_CLIENT = 2; |
||
49 | |||
50 | /** |
||
51 | * @var mixed |
||
52 | */ |
||
53 | const CONFIG_DEFAULT_SSL = false; |
||
54 | |||
55 | /** |
||
56 | * @var mixed |
||
57 | */ |
||
58 | const CONFIG_DEFAULT_SSL_METHOD = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; |
||
59 | |||
60 | /** |
||
61 | * @var mixed |
||
62 | */ |
||
63 | const CONFIG_DEFAULT_SSL_NAME = ''; |
||
64 | |||
65 | /** |
||
66 | * @var mixed |
||
67 | */ |
||
68 | const CONFIG_DEFAULT_SSL_VERIFY_SIGN = false; |
||
69 | |||
70 | /** |
||
71 | * @var mixed |
||
72 | */ |
||
73 | const CONFIG_DEFAULT_SSL_VERIFY_PEER = false; |
||
74 | |||
75 | /** |
||
76 | * @var mixed |
||
77 | */ |
||
78 | const CONFIG_DEFAULT_SSL_VERIFY_DEPTH = 10; |
||
79 | |||
80 | /** |
||
81 | * @var int |
||
82 | */ |
||
83 | protected $crypto = 0; |
||
84 | |||
85 | /** |
||
86 | * @var int |
||
87 | */ |
||
88 | protected $cryptoMethod = 0; |
||
89 | |||
90 | /** |
||
91 | * @var array |
||
92 | */ |
||
93 | protected $config = []; |
||
94 | |||
95 | /** |
||
96 | * @var bool[] |
||
97 | */ |
||
98 | private $cachedEndpoint = []; |
||
99 | |||
100 | /** |
||
101 | * @param string|resource $endpointOrResource |
||
102 | * @param LoopInterface $loop |
||
103 | * @param mixed[] $config |
||
104 | * @throws InstantiationException |
||
105 | */ |
||
106 | 18 | public function __construct($endpointOrResource, LoopInterface $loop, $config = []) |
|
107 | { |
||
108 | try |
||
109 | { |
||
110 | 18 | $this->configure($config); |
|
111 | |||
112 | 18 | if (!is_resource($endpointOrResource)) |
|
113 | { |
||
114 | 18 | $endpointOrResource = $this->createClient($endpointOrResource, $config); |
|
0 ignored issues
–
show
|
|||
115 | } |
||
116 | |||
117 | 16 | parent::__construct($endpointOrResource, $loop); |
|
0 ignored issues
–
show
$loop is of type object<Dazzle\Loop\LoopInterface> , but the function expects a boolean .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
118 | |||
119 | 16 | $this->read(); |
|
120 | } |
||
121 | 2 | catch (Error $ex) |
|
122 | { |
||
123 | throw new InstantiationException('SocketClient could not be created.', 0, $ex); |
||
124 | } |
||
125 | 2 | catch (Exception $ex) |
|
126 | { |
||
127 | 2 | throw new InstantiationException('SocketClient could not be created.', 0, $ex); |
|
128 | } |
||
129 | 16 | } |
|
130 | |||
131 | /** |
||
132 | * @override |
||
133 | * @inheritDoc |
||
134 | */ |
||
135 | 1 | public function stop() |
|
136 | { |
||
137 | 1 | $this->close(); |
|
138 | 1 | } |
|
139 | |||
140 | /** |
||
141 | * @override |
||
142 | * @inheritDoc |
||
143 | */ |
||
144 | 5 | public function getLocalEndpoint() |
|
145 | { |
||
146 | 5 | return $this->parseEndpoint(false); |
|
147 | } |
||
148 | |||
149 | /** |
||
150 | * @override |
||
151 | * @inheritDoc |
||
152 | */ |
||
153 | 5 | public function getRemoteEndpoint() |
|
154 | { |
||
155 | 5 | return $this->parseEndpoint(true); |
|
156 | } |
||
157 | |||
158 | /** |
||
159 | * @override |
||
160 | * @inheritDoc |
||
161 | */ |
||
162 | 3 | public function getLocalAddress() |
|
163 | { |
||
164 | 3 | $endpoint = explode('://', $this->getLocalEndpoint(), 2); |
|
165 | |||
166 | 3 | return isset($endpoint[1]) ? $endpoint[1] : $endpoint[0]; |
|
167 | } |
||
168 | |||
169 | /** |
||
170 | * @override |
||
171 | * @inheritDoc |
||
172 | */ |
||
173 | 1 | public function getLocalHost() |
|
174 | { |
||
175 | 1 | $address = explode(':', $this->getLocalAddress(), 2); |
|
176 | |||
177 | 1 | return $address[0]; |
|
178 | } |
||
179 | |||
180 | /** |
||
181 | * @override |
||
182 | * @inheritDoc |
||
183 | */ |
||
184 | 1 | public function getLocalPort() |
|
185 | { |
||
186 | 1 | $address = explode(':', $this->getLocalAddress(), 2); |
|
187 | |||
188 | 1 | return isset($address[1]) ? $address[1] : ''; |
|
189 | } |
||
190 | |||
191 | /** |
||
192 | * @override |
||
193 | * @inheritDoc |
||
194 | */ |
||
195 | 1 | public function getLocalProtocol() |
|
196 | { |
||
197 | 1 | $endpoint = explode('://', $this->getLocalEndpoint(), 2); |
|
198 | |||
199 | 1 | return isset($endpoint[0]) ? $endpoint[0] : ''; |
|
200 | } |
||
201 | |||
202 | /** |
||
203 | * @override |
||
204 | * @inheritDoc |
||
205 | */ |
||
206 | 3 | public function getRemoteAddress() |
|
207 | { |
||
208 | 3 | $endpoint = explode('://', $this->getRemoteEndpoint(), 2); |
|
209 | |||
210 | 3 | return isset($endpoint[1]) ? $endpoint[1] : $endpoint[0]; |
|
211 | } |
||
212 | |||
213 | /** |
||
214 | * @override |
||
215 | * @inheritDoc |
||
216 | */ |
||
217 | 1 | public function getRemoteHost() |
|
218 | { |
||
219 | 1 | $address = explode(':', $this->getRemoteAddress(), 2); |
|
220 | |||
221 | 1 | return $address[0]; |
|
222 | } |
||
223 | |||
224 | /** |
||
225 | * @override |
||
226 | * @inheritDoc |
||
227 | */ |
||
228 | 1 | public function getRemotePort() |
|
229 | { |
||
230 | 1 | $address = explode(':', $this->getRemoteAddress(), 2); |
|
231 | |||
232 | 1 | return isset($address[1]) ? $address[1] : ''; |
|
233 | } |
||
234 | |||
235 | /** |
||
236 | * @override |
||
237 | * @inheritDoc |
||
238 | */ |
||
239 | 1 | public function getRemoteProtocol() |
|
240 | { |
||
241 | 1 | $endpoint = explode('://', $this->getRemoteEndpoint(), 2); |
|
242 | |||
243 | 1 | return isset($endpoint[0]) ? $endpoint[0] : ''; |
|
244 | } |
||
245 | |||
246 | /** |
||
247 | * @override |
||
248 | * @inheritDoc |
||
249 | */ |
||
250 | 1 | public function isEncrypted() |
|
251 | { |
||
252 | 1 | return $this->crypto !== 0; |
|
253 | } |
||
254 | |||
255 | /** |
||
256 | * Create the client resource. |
||
257 | * |
||
258 | * This method creates client resource for socket connections. |
||
259 | * |
||
260 | * @param string $endpoint |
||
261 | * @param mixed[] $config |
||
262 | * @return resource |
||
263 | * @throws LogicException |
||
264 | */ |
||
265 | 18 | protected function createClient($endpoint, $config = []) |
|
266 | { |
||
267 | 18 | $ssl = $this->config['ssl']; |
|
268 | 18 | $name = $this->config['ssl_name']; |
|
269 | 18 | $verifySign = $this->config['ssl_verify_sign']; |
|
270 | 18 | $verifyPeer = $this->config['ssl_verify_peer']; |
|
271 | 18 | $verifyDepth = $this->config['ssl_verify_depth']; |
|
272 | |||
273 | 18 | $context = []; |
|
274 | 18 | $context['socket'] = [ |
|
275 | 18 | 'connect' => $endpoint |
|
276 | ]; |
||
277 | 18 | $context['ssl'] = [ |
|
278 | 18 | 'capture_peer_cert' => true, |
|
279 | 'capture_peer_chain' => true, |
||
280 | 'capture_peer_cert_chain' => true, |
||
281 | 18 | 'allow_self_signed' => !$verifySign, |
|
282 | 18 | 'verify_peer' => $verifyPeer, |
|
283 | 18 | 'verify_peer_name' => $verifyPeer, |
|
284 | 18 | 'verify_depth' => $verifyDepth, |
|
285 | 18 | 'SNI_enabled' => $name !== '', |
|
286 | 18 | 'SNI_server_name' => $name, |
|
287 | 18 | 'peer_name' => $name, |
|
288 | 'disable_compression' => true, |
||
289 | 'honor_cipher_order' => true, |
||
290 | ]; |
||
291 | |||
292 | 18 | if ($ssl && isset($config['ssl_cafile'])) |
|
293 | { |
||
294 | $context['ssl']['cafile'] = $config['ssl_cafile']; |
||
295 | } |
||
296 | |||
297 | 18 | if ($ssl && isset($config['ssl_capath'])) |
|
298 | { |
||
299 | $context['ssl']['capath'] = $config['ssl_capath']; |
||
300 | } |
||
301 | |||
302 | 18 | $context = stream_context_create($context); |
|
303 | // Error reporting suppressed since stream_socket_client() emits an E_WARNING on failure. |
||
304 | 18 | $socket = @stream_socket_client( |
|
305 | 18 | $endpoint, |
|
306 | 18 | $errno, |
|
307 | 18 | $errstr, |
|
308 | 18 | 0, // Timeout does not apply for async connect. |
|
309 | 18 | STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT, |
|
310 | 18 | $context |
|
311 | ); |
||
312 | |||
313 | 18 | View Code Duplication | if (!$socket || $errno > 0) |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
314 | { |
||
315 | 2 | throw new LogicException( |
|
316 | 2 | sprintf('Could not connect socket [%s] because of error [%d; %s]', $endpoint, $errno, $errstr) |
|
317 | ); |
||
318 | } |
||
319 | |||
320 | 16 | stream_set_blocking($socket, false); |
|
321 | |||
322 | 16 | return $socket; |
|
323 | } |
||
324 | |||
325 | /** |
||
326 | * Handle socket encryption. |
||
327 | * |
||
328 | * @internal |
||
329 | */ |
||
330 | 1 | public function handleEncrypt() |
|
331 | { |
||
332 | 1 | $ex = null; |
|
333 | |||
334 | try |
||
335 | { |
||
336 | 1 | if ($this->isEncrypted()) |
|
337 | { |
||
338 | return; |
||
339 | } |
||
340 | |||
341 | 1 | $this->encrypt($this->config['ssl_method']); |
|
342 | |||
343 | 1 | if ($this->isEncrypted()) |
|
344 | { |
||
345 | 1 | $this->pause(); |
|
0 ignored issues
–
show
The method
pause() does not seem to exist on object<Dazzle\Socket\Socket> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||
346 | 1 | $this->resume(); |
|
0 ignored issues
–
show
The method
resume() does not seem to exist on object<Dazzle\Socket\Socket> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||
347 | } |
||
348 | } |
||
349 | catch (Error $ex) |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
350 | {} |
||
351 | catch (Exception $ex) |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
352 | {} |
||
353 | |||
354 | 1 | if ($ex !== null) |
|
355 | { |
||
356 | $this->close(); |
||
357 | $this->emit('error', [ $this, $ex ]); |
||
358 | } |
||
359 | 1 | } |
|
360 | |||
361 | /** |
||
362 | * @internal |
||
363 | * @override |
||
364 | * @inheritDoc |
||
365 | */ |
||
366 | 3 | public function handleRead() |
|
367 | { |
||
368 | 3 | $ex = null; |
|
369 | |||
370 | try |
||
371 | { |
||
372 | 3 | $data = fread($this->resource, $this->bufferSize); |
|
373 | |||
374 | 3 | if ($data !== '' && $data !== false) |
|
375 | { |
||
376 | 3 | $this->emit('data', [ $this, $data ]); |
|
377 | 3 | $this->emit('end', [ $this ]); |
|
378 | } |
||
379 | |||
380 | 3 | if ($data === '' || $data === false || !is_resource($this->resource) || feof($this->resource)) |
|
381 | { |
||
382 | 3 | $this->close(); |
|
383 | } |
||
384 | } |
||
385 | catch (Error $ex) |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
386 | {} |
||
387 | catch (Exception $ex) |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
388 | {} |
||
389 | |||
390 | 3 | if ($ex !== null) |
|
391 | { |
||
392 | $this->emit('error', [ $this, $ex ]); |
||
393 | } |
||
394 | 3 | } |
|
395 | |||
396 | /** |
||
397 | * @internal |
||
398 | * @override |
||
399 | * @inheritDoc |
||
400 | */ |
||
401 | 3 | public function handleWrite() |
|
402 | { |
||
403 | 3 | $ex = null; |
|
404 | |||
405 | try |
||
406 | { |
||
407 | 3 | parent::handleWrite(); |
|
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
Dazzle\Stream\Stream as the method handleWrite() does only exist in the following sub-classes of Dazzle\Stream\Stream : Dazzle\Socket\Socket , Dazzle\Stream\AsyncStream . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
408 | } |
||
409 | catch (Error $ex) |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
410 | {} |
||
411 | catch (Exception $ex) |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
412 | {} |
||
413 | |||
414 | 3 | if ($ex !== null) |
|
415 | { |
||
416 | $this->emit('error', [ $this, $ex ]); |
||
417 | } |
||
418 | 3 | } |
|
419 | |||
420 | /** |
||
421 | * @internal |
||
422 | * @override |
||
423 | * @inheritDoc |
||
424 | */ |
||
425 | 16 | public function handleClose() |
|
426 | { |
||
427 | 16 | $this->pause(); |
|
0 ignored issues
–
show
The method
pause() does not seem to exist on object<Dazzle\Socket\Socket> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||
428 | |||
429 | 16 | if (is_resource($this->resource)) |
|
430 | { |
||
431 | // http://chat.stackoverflow.com/transcript/message/7727858#7727858 |
||
432 | 16 | stream_socket_shutdown($this->resource, STREAM_SHUT_RDWR); |
|
433 | 16 | stream_set_blocking($this->resource, 0); |
|
434 | 16 | fclose($this->resource); |
|
435 | } |
||
436 | 16 | } |
|
437 | |||
438 | /** |
||
439 | * Get function that should be invoked on read event. |
||
440 | * |
||
441 | * @return callable |
||
442 | */ |
||
443 | 16 | protected function getHandleReadFunction() |
|
444 | { |
||
445 | 16 | return $this->config['ssl'] === true && !$this->isEncrypted() |
|
446 | 1 | ? [ $this, 'handleEncrypt' ] |
|
447 | 16 | : [ $this, 'handleRead' ]; |
|
448 | } |
||
449 | |||
450 | /** |
||
451 | * Get function that should be invoked on write event. |
||
452 | * |
||
453 | * @return callable |
||
454 | */ |
||
455 | 3 | protected function getHandleWriteFunction() |
|
456 | { |
||
457 | 3 | return $this->config['ssl'] === true && !$this->isEncrypted() |
|
458 | 1 | ? [ $this, 'handleEncrypt' ] |
|
459 | 3 | : [ $this, 'handleWrite' ]; |
|
460 | } |
||
461 | |||
462 | /** |
||
463 | * Configure socket. |
||
464 | * |
||
465 | * @param string[] $config |
||
466 | */ |
||
467 | 18 | View Code Duplication | private function configure($config = []) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
468 | { |
||
469 | 18 | $this->config = $config; |
|
470 | |||
471 | 18 | $this->configureVariable('ssl'); |
|
472 | 18 | $this->configureVariable('ssl_method'); |
|
473 | 18 | $this->configureVariable('ssl_name'); |
|
474 | 18 | $this->configureVariable('ssl_verify_sign'); |
|
475 | 18 | $this->configureVariable('ssl_verify_peer'); |
|
476 | 18 | $this->configureVariable('ssl_verify_depth'); |
|
477 | 18 | } |
|
478 | |||
479 | /** |
||
480 | * Configure config variable. |
||
481 | * |
||
482 | * @param $configKey |
||
483 | */ |
||
484 | 18 | private function configureVariable($configKey) |
|
485 | { |
||
486 | 18 | $configStaticKey = 'CONFIG_DEFAULT_' . strtoupper($configKey); |
|
487 | 18 | $this->config[$configKey] = isset($this->config[$configKey]) ? $this->config[$configKey] : constant("static::$configStaticKey"); |
|
488 | 18 | } |
|
489 | |||
490 | /** |
||
491 | * @param bool $wantPeer |
||
492 | * @return string |
||
0 ignored issues
–
show
|
|||
493 | */ |
||
494 | 10 | private function parseEndpoint($wantPeer = false) |
|
495 | { |
||
496 | 10 | $wantIndex = (int)$wantPeer; |
|
497 | |||
498 | 10 | if (isset($this->cachedEndpoint[$wantIndex])) |
|
499 | { |
||
500 | return $this->cachedEndpoint[$wantIndex]; |
||
501 | } |
||
502 | |||
503 | 10 | if (get_resource_type($this->resource) === Socket::TYPE_UNKNOWN) |
|
504 | { |
||
505 | return ''; |
||
506 | } |
||
507 | |||
508 | 10 | $name = stream_socket_get_name($this->resource, $wantPeer); |
|
509 | 10 | $type = $this->getStreamType(); |
|
510 | |||
511 | View Code Duplication | switch ($type) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
512 | { |
||
513 | 10 | case Socket::TYPE_UNIX: |
|
514 | $transport = 'unix://'; |
||
515 | $endpoint = $transport . $name; |
||
516 | break; |
||
517 | |||
518 | 10 | case Socket::TYPE_TCP: |
|
519 | 10 | $transport = 'tcp://'; |
|
520 | 10 | if (substr_count($name, ':') > 1) |
|
521 | { |
||
522 | $parts = explode(':', $name); |
||
523 | $count = count($parts); |
||
524 | $port = $parts[$count - 1]; |
||
525 | unset($parts[$count - 1]); |
||
526 | $endpoint = $transport.'[' . implode(':', $parts) . ']:' . $port; |
||
527 | } |
||
528 | else |
||
529 | { |
||
530 | 10 | $endpoint = $transport . $name; |
|
531 | } |
||
532 | 10 | break; |
|
533 | |||
534 | case Socket::TYPE_UDP: |
||
535 | $transport = 'udp://'; |
||
536 | $endpoint = $transport . $name; |
||
537 | break; |
||
538 | |||
539 | default: |
||
540 | $endpoint = ''; |
||
541 | } |
||
542 | |||
543 | 10 | $this->cachedEndpoint[$wantIndex] = $endpoint; |
|
544 | |||
545 | 10 | return $endpoint; |
|
546 | } |
||
547 | |||
548 | /** |
||
549 | * @override |
||
550 | * @inheritDoc |
||
551 | */ |
||
552 | 1 | private function encrypt($method) |
|
553 | { |
||
554 | 1 | $type = $this->selectCryptoType($method); |
|
555 | |||
556 | 1 | if ($type === self::CRYPTO_TYPE_UNKNOWN) |
|
557 | { |
||
558 | throw new ExecutionException('Socket encryption method is invalid!'); |
||
559 | } |
||
560 | |||
561 | 1 | $resource = $this->getResource(); |
|
562 | |||
563 | 1 | if ($type === self::CRYPTO_TYPE_SERVER && $this->cryptoMethod === 0) |
|
564 | { |
||
565 | 1 | $raw = @stream_socket_recvfrom($resource, 11, STREAM_PEEK); |
|
566 | |||
567 | 1 | if ($raw === '') |
|
568 | { |
||
569 | return; |
||
570 | } |
||
571 | |||
572 | 1 | if (11 > strlen($raw)) |
|
573 | { |
||
574 | throw new ExecutionException('Failed to read crypto handshake.'); |
||
575 | } |
||
576 | |||
577 | 1 | $data = unpack('ctype/nversion/nlength/Nembed/nmax-version', $raw); |
|
578 | 1 | if (0x16 !== $data['type']) |
|
579 | { |
||
580 | throw new ExecutionException('Invalid crypto handshake.'); |
||
581 | } |
||
582 | |||
583 | // Check if version was available in $method. |
||
584 | 1 | $version = $this->selectCryptoVersion($data['max-version']); |
|
585 | 1 | if ($method & $version) |
|
586 | { |
||
587 | 1 | $method = $version; |
|
588 | } |
||
589 | } |
||
590 | |||
591 | 1 | $this->cryptoMethod = $method; |
|
592 | 1 | $result = @stream_socket_enable_crypto($resource, true, $this->cryptoMethod); |
|
593 | |||
594 | 1 | if ($result === 0) |
|
595 | { |
||
596 | 1 | return; |
|
597 | } |
||
598 | 1 | else if (!$result) |
|
599 | { |
||
600 | $message = 'Socket encryption failed.'; |
||
601 | if ($error = error_get_last()) |
||
602 | { |
||
603 | $message .= sprintf(' Errno: %d; %s', $error['type'], $error['message']); |
||
604 | } |
||
605 | throw new ExecutionException($message); |
||
606 | } |
||
607 | else |
||
608 | { |
||
609 | 1 | $this->crypto = $this->cryptoMethod; |
|
610 | } |
||
611 | 1 | } |
|
612 | |||
613 | /** |
||
614 | * Checks type of crypto. |
||
615 | * |
||
616 | * @param int $version |
||
617 | * @return int |
||
618 | */ |
||
619 | 1 | private function selectCryptoType($version) |
|
620 | { |
||
621 | switch ($version) |
||
622 | { |
||
623 | 1 | case STREAM_CRYPTO_METHOD_SSLv3_SERVER: |
|
624 | 1 | case STREAM_CRYPTO_METHOD_TLSv1_0_SERVER: |
|
625 | 1 | case STREAM_CRYPTO_METHOD_TLSv1_1_SERVER: |
|
626 | 1 | case STREAM_CRYPTO_METHOD_TLSv1_2_SERVER: |
|
627 | 1 | return self::CRYPTO_TYPE_SERVER; |
|
628 | |||
629 | 1 | case STREAM_CRYPTO_METHOD_SSLv3_CLIENT: |
|
630 | 1 | case STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT: |
|
631 | 1 | case STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT: |
|
632 | 1 | case STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT: |
|
633 | 1 | return self::CRYPTO_TYPE_CLIENT; |
|
634 | |||
635 | default: |
||
636 | return self::CRYPTO_TYPE_UNKNOWN; |
||
637 | } |
||
638 | } |
||
639 | |||
640 | /** |
||
641 | * Returns highest supported crypto method constant based on protocol version identifier. |
||
642 | * |
||
643 | * @param int $version |
||
644 | * @return int |
||
645 | */ |
||
646 | 1 | private function selectCryptoVersion($version) |
|
647 | { |
||
648 | switch ($version) |
||
649 | { |
||
650 | 1 | case 0x300: return STREAM_CRYPTO_METHOD_SSLv3_SERVER; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
651 | 1 | case 0x301: return STREAM_CRYPTO_METHOD_TLSv1_0_SERVER; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
652 | 1 | case 0x302: return STREAM_CRYPTO_METHOD_TLSv1_1_SERVER; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
653 | 1 | default: return STREAM_CRYPTO_METHOD_TLSv1_2_SERVER; |
|
0 ignored issues
–
show
The default body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a default statement must start on the line immediately following the statement. switch ($expr) {
default:
doSomething(); //right
break;
}
switch ($expr) {
default:
doSomething(); //wrong
break;
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
654 | } |
||
655 | } |
||
656 | } |
||
657 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.