]> granicus.if.org Git - php/commitdiff
Add crypto info to stream_get_meta_data() result on encrypted streams
authorDaniel Lowrey <rdlowrey@php.net>
Tue, 10 Mar 2015 04:30:38 +0000 (22:30 -0600)
committerDaniel Lowrey <rdlowrey@php.net>
Tue, 10 Mar 2015 05:15:57 +0000 (23:15 -0600)
A "crypto" key is added to the output of stream_get_meta_data() calls
when invoked using a stream on which crypto is currently active. The
new key's associated array contains the following keys:

 - protocol (string e.g. TLSv1.2, TLSv1.1, etc)
 - cipher_name (string)
 - cipher_bits (int)
 - cipher_version (string)

If the TLS ALPN extension was used to successfully negotiate an
application protocol that protocol's identifier is stored in the
following key:

 - alpn_protocol

If no ALPN protocol was negotiated the "alpn_protocol" key is not
present in the crypto meta data array. More meta information
concerning the stream's active encryption state may be added in the
future.

ext/openssl/xp_ssl.c

index 1b5bba73e06d5aa182093977d794f3dc05d0301e..7f0764ec24be051625f2b6b3d1d46706e8adfa90 100644 (file)
@@ -1601,7 +1601,6 @@ int php_openssl_setup_crypto(php_stream *stream,
                                sslsock->ctx = NULL;
                                return FAILURE;
                        }
-
                        if (sslsock->is_client) {
                                SSL_CTX_set_alpn_protos(sslsock->ctx, alpn, alpn_len);
                        } else {
@@ -2359,6 +2358,58 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val
        php_stream_xport_param *xparam = (php_stream_xport_param *)ptrparam;
 
        switch (option) {
+               case PHP_STREAM_OPTION_META_DATA_API:
+                       if (sslsock->ssl_active) {
+                               zval tmp;
+                               char *proto_str;
+                               const SSL_CIPHER *cipher;
+
+                               array_init(&tmp);
+
+                               switch (SSL_version(sslsock->ssl_handle)) {
+#ifdef HAVE_TLS12
+                                       case TLS1_2_VERSION: proto_str = "TLSv1.2"; break;
+#endif
+#ifdef HAVE_TLS11
+                                       case TLS1_1_VERSION: proto_str = "TLSv1.1"; break;
+#endif
+                                       case TLS1_VERSION: proto_str = "TLSv1"; break;
+#ifdef HAVE_SSL3
+                                       case SSL3_VERSION: proto_str = "SSLv3"; break;
+#endif
+#ifdef HAVE_SSL2
+                                       case SSL2_VERSION: proto_str = "SSLv2"; break;
+#endif
+                                       default: proto_str = "UNKNOWN";
+                               }
+
+                               cipher = SSL_get_current_cipher(sslsock->ssl_handle);
+
+                               add_assoc_string(&tmp, "protocol", proto_str);
+                               add_assoc_string(&tmp, "cipher_name", (char *) SSL_CIPHER_get_name(cipher));
+                               add_assoc_long(&tmp, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL));
+                               add_assoc_string(&tmp, "cipher_version", SSL_CIPHER_get_version(cipher));
+
+#ifdef HAVE_TLS_ALPN
+                               {
+                                       const unsigned char *alpn_proto = NULL;
+                                       unsigned int alpn_proto_len = 0;
+
+                                       SSL_get0_alpn_selected(sslsock->ssl_handle, &alpn_proto, &alpn_proto_len);
+                                       if (alpn_proto) {
+                                               add_assoc_stringl(&tmp, "alpn_protocol", (char *)alpn_proto, alpn_proto_len);
+                                       }
+                               }
+#endif
+                               add_assoc_zval((zval *)ptrparam, "crypto", &tmp);
+                       }
+
+                       add_assoc_bool((zval *)ptrparam, "timed_out", sslsock->s.timeout_event);
+                       add_assoc_bool((zval *)ptrparam, "blocked", sslsock->s.is_blocked);
+                       add_assoc_bool((zval *)ptrparam, "eof", stream->eof);
+
+                       return PHP_STREAM_OPTION_RETURN_OK;
+
                case PHP_STREAM_OPTION_CHECK_LIVENESS:
                        {
                                struct timeval tv;