php / php/php-src

Problem with enabling crypto on stream socket connection

Đang mở
#9,261 6 bình luận 0 reaction 1 người được giao Xem trên GitHub

@bukka đang làm issue này rồi.

Từ ngày 8/8/2022.

Bug Extension: openssl
Ngôn ngữ chính
C
Star
40.4k
Fork
8.2k
Merge trung bình
2 ngày 13 giờ
Pull request đã merge (30 ngày)
96

Mô tả

Description

Hi.

I'm trying to deal with some things in php and I can't find my workaround about it and it starting to feel like there is something buggy. I tried looking on internet even asked on stackoverflow but nothing.

My goal is to create stream socket connection with disabled SSL but request certificate, then analyze it and update connection parameters. It works great on server with SSL but when I try it on server without SSL I'm not able to write into that connection even when I try to disable crypto on it.

<?php
$context = stream_context_create([
    'socket' => [
        'tcp_nodelay' => true,
    ],
    'ssl' => [
        'verify_peer' => false,
        'verify_peer_name' => false,
        'SNI_enabled' => false,
        'allow_self_signed' => true,
        'capture_peer_cert' => true,
        'capture_peer_cert_chain' => true
    ]
]);

$stream = stream_socket_client('tcp://' . $this->ip . ':' . $this->port, $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $context);
if ($stream === false) {
    throw new ConnectException($errstr, $errno);
}

if (!stream_set_blocking($stream, true)) {
    throw new ConnectException('Cannot set socket into blocking mode');
}

$enableCrypto = stream_socket_enable_crypto($stream, true, STREAM_CRYPTO_METHOD_ANY_CLIENT);
if ($enableCrypto === true) {
    $params = stream_context_get_params($stream);

    if (isset($params['options']['ssl']['peer_certificate']) && is_resource($params['options']['ssl']['peer_certificate'])) {
        $cert = openssl_x509_parse($params['options']['ssl']['peer_certificate']);
        stream_context_set_params($stream, [
            'ssl' => [
                'verify_peer' => true,
                'verify_peer_name' => true,
                'SNI_enabled' => true,
                'peer_name' => $cert['subject']['CN'],
                'allow_self_signed' => count($params['options']['ssl']['peer_certificate_chain']) == 1 && $cert['subject'] == $cert['issuer']
            ]
        ]);
    }
} else {
    stream_socket_enable_crypto($stream, false, STREAM_CRYPTO_METHOD_ANY_CLIENT);
}

You can see in the code what I described. I'm testing the connectivity against graph database Neo4j but I believe it doesn't matter. SSL certificate request is executed at first stream_socket_enable_crypto. Maybe there is different way to request capture of that certificate, I don't know.

What is weird when I enable crypto with stream_socket_enable_crypto against non-SSL host I get warning:

Warning: stream_socket_enable_crypto(): SSL: The operation completed successfully.

and $enableCrypto contains (int)0. The warning doesn't make sense.

After all this logic the connection is still open but when I try to use it I get error

Notice: fwrite(): send of 16 bytes failed with errno=10053 An established connection was aborted by the software in your host machine.

At this moment it feels like the encryption is enabled on client side (php) and the messages sent over socket therefore are not properly decoded on host, because there is no encryption at all. Like stream_socket_enable_crypto($stream, false) did not disable crypto.

PHP Version

PHP 7.4.16 with OpenSSL/1.1.1k and PHP 8.1.9 with OpenSSL/1.1.1q

Operating System

Windows 10

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.