]> granicus.if.org Git - php/commitdiff
Add 'capture_session_meta' context option
authorDaniel Lowrey <rdlowrey@php.net>
Tue, 11 Feb 2014 13:42:29 +0000 (06:42 -0700)
committerDaniel Lowrey <rdlowrey@php.net>
Fri, 21 Feb 2014 00:10:06 +0000 (17:10 -0700)
ext/openssl/tests/session_meta_capture.phpt [new file with mode: 0644]
ext/openssl/xp_ssl.c

diff --git a/ext/openssl/tests/session_meta_capture.phpt b/ext/openssl/tests/session_meta_capture.phpt
new file mode 100644 (file)
index 0000000..8ef0f87
--- /dev/null
@@ -0,0 +1,73 @@
+--TEST--
+Capture SSL session meta array in stream context
+--SKIPIF--
+<?php
+if (!extension_loaded("openssl")) die("skip");
+if (!function_exists('pcntl_fork')) die("skip no fork");
+if (OPENSSL_VERSION_NUMBER < 0x10001001) die("skip OpenSSLv1.0.1 required");
+--FILE--
+<?php
+$flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
+$ctx = stream_context_create(['ssl' => [
+    'local_cert' => __DIR__ . '/bug54992.pem',
+    'allow_self_signed' => true
+]]);
+$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, $flags, $ctx);
+
+$pid = pcntl_fork();
+if ($pid == -1) {
+    die('could not fork');
+} else if ($pid) {
+
+    // Base SSL context values
+    $sslCtxVars = array(
+        'verify_peer' => TRUE,
+        'cafile' => __DIR__ . '/bug54992-ca.pem',
+        'CN_match' => 'bug54992.local', // common name from the server's "local_cert" PEM file
+        'capture_session_meta' => TRUE
+    );
+
+    // SSLv3
+    $ctxCopy = $sslCtxVars;
+    $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
+    $ctx = stream_context_create(array('ssl' => $ctxCopy));
+    stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx);
+    $meta = stream_context_get_options($ctx)['ssl']['session_meta'];
+    var_dump($meta['protocol']);
+
+    // TLSv1
+    $ctxCopy = $sslCtxVars;
+    $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT;
+    $ctx = stream_context_create(array('ssl' => $ctxCopy));
+    stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx);
+    $meta = stream_context_get_options($ctx)['ssl']['session_meta'];
+    var_dump($meta['protocol']);
+
+    // TLSv1.1
+    $ctxCopy = $sslCtxVars;
+    $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
+    $ctx = stream_context_create(array('ssl' => $ctxCopy));
+    stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx);
+    $meta = stream_context_get_options($ctx)['ssl']['session_meta'];
+    var_dump($meta['protocol']);
+
+    // TLSv1.2
+    $ctxCopy = $sslCtxVars;
+    $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
+    $ctx = stream_context_create(array('ssl' => $ctxCopy));
+    stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx);
+    $meta = stream_context_get_options($ctx)['ssl']['session_meta'];
+    var_dump($meta['protocol']);
+
+} else {
+    @pcntl_wait($status);
+    @stream_socket_accept($server, 1);
+    @stream_socket_accept($server, 1);
+    @stream_socket_accept($server, 1);
+    @stream_socket_accept($server, 1);
+}
+--EXPECTF--
+string(5) "SSLv3"
+string(5) "TLSv1"
+string(7) "TLSv1.1"
+string(7) "TLSv1.2"
index 99995b6814cb72b7eb08c71fba7b0ee71955068c..aa1d50e64d547e86daa4b92ce4985ef5d12d948f 100644 (file)
@@ -456,6 +456,31 @@ static inline int php_openssl_setup_crypto(php_stream *stream,
        return 0;
 }
 
+static zval *php_capture_ssl_session_meta(SSL *ssl_handle)
+{
+       zval *meta_arr;
+       char *proto_str;
+       long proto = SSL_version(ssl_handle);
+       const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_handle);
+
+       switch (proto) {
+               case TLS1_2_VERSION: proto_str = "TLSv1.2"; break;
+               case TLS1_1_VERSION: proto_str = "TLSv1.1"; break;
+               case TLS1_VERSION: proto_str = "TLSv1"; break;
+               case SSL3_VERSION: proto_str = "SSLv3"; break;
+               case SSL2_VERSION: proto_str = "SSLv2"; break;
+               default: proto_str = "UNKNOWN";
+       }
+
+       MAKE_STD_ZVAL(meta_arr);
+       array_init(meta_arr);
+       add_assoc_string(meta_arr, "protocol", proto_str, 1);
+       add_assoc_string(meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher), 1);
+       add_assoc_long(meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL));
+       add_assoc_string(meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher), 1);
+
+       return meta_arr;
+}
 
 static inline int php_openssl_enable_crypto(php_stream *stream, php_openssl_netstream_data_t *sslsock, php_stream_xport_crypto_param *cparam TSRMLS_DC)
 {
@@ -581,6 +606,18 @@ static inline int php_openssl_enable_crypto(php_stream *stream, php_openssl_nets
                                if (stream->context) {
                                        zval **val, *zcert;
 
+                                       if (SUCCESS == php_stream_context_get_option(
+                                                               stream->context, "ssl",
+                                                               "capture_session_meta", &val) &&
+                                                       zend_is_true(*val)) {
+                                               zval *meta_arr = php_capture_ssl_session_meta(sslsock->ssl_handle);
+                                               php_stream_context_set_option(stream->context,
+                                                               "ssl", "session_meta",
+                                                               meta_arr);
+                                               zval_dtor(meta_arr);
+                                               efree(meta_arr);
+                                       }
+
                                        if (SUCCESS == php_stream_context_get_option(
                                                                stream->context, "ssl",
                                                                "capture_peer_cert", &val) &&