PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/openssl - xp_ssl.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 278 447 62.2 %
Date: 2014-10-16 Functions: 14 15 93.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 5                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2014 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Author: Wez Furlong <wez@thebrainroom.com>                           |
      16             :   +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : #include "php.h"
      22             : #include "ext/standard/file.h"
      23             : #include "ext/standard/url.h"
      24             : #include "streams/php_streams_int.h"
      25             : #include "ext/standard/php_smart_str.h"
      26             : #include "php_network.h"
      27             : #include "php_openssl.h"
      28             : #include <openssl/ssl.h>
      29             : #include <openssl/x509.h>
      30             : #include <openssl/err.h>
      31             : 
      32             : #ifdef PHP_WIN32
      33             : #include "win32/time.h"
      34             : #endif
      35             : 
      36             : #ifdef NETWARE
      37             : #include <sys/select.h>
      38             : #endif
      39             : 
      40             : int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC);
      41             : SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC);
      42             : int php_openssl_get_x509_list_id(void);
      43             : 
      44             : /* This implementation is very closely tied to the that of the native
      45             :  * sockets implemented in the core.
      46             :  * Don't try this technique in other extensions!
      47             :  * */
      48             : 
      49             : typedef struct _php_openssl_netstream_data_t {
      50             :         php_netstream_data_t s;
      51             :         SSL *ssl_handle;
      52             :         SSL_CTX *ctx;
      53             :         struct timeval connect_timeout;
      54             :         int enable_on_connect;
      55             :         int is_client;
      56             :         int ssl_active;
      57             :         php_stream_xport_crypt_method_t method;
      58             :         char *sni;
      59             :         unsigned state_set:1;
      60             :         unsigned _spare:31;
      61             : } php_openssl_netstream_data_t;
      62             : 
      63             : php_stream_ops php_openssl_socket_ops;
      64             : 
      65             : /* it doesn't matter that we do some hash traversal here, since it is done only
      66             :  * in an error condition arising from a network connection problem */
      67           0 : static int is_http_stream_talking_to_iis(php_stream *stream TSRMLS_DC)
      68             : {
      69           0 :         if (stream->wrapperdata && stream->wrapper && strcasecmp(stream->wrapper->wops->label, "HTTP") == 0) {
      70             :                 /* the wrapperdata is an array zval containing the headers */
      71             :                 zval **tmp;
      72             : 
      73             : #define SERVER_MICROSOFT_IIS    "Server: Microsoft-IIS"
      74             : #define SERVER_GOOGLE "Server: GFE/"
      75             :                 
      76           0 :                 zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream->wrapperdata));
      77           0 :                 while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(stream->wrapperdata), (void**)&tmp)) {
      78             : 
      79           0 :                         if (strncasecmp(Z_STRVAL_PP(tmp), SERVER_MICROSOFT_IIS, sizeof(SERVER_MICROSOFT_IIS)-1) == 0) {
      80           0 :                                 return 1;
      81           0 :                         } else if (strncasecmp(Z_STRVAL_PP(tmp), SERVER_GOOGLE, sizeof(SERVER_GOOGLE)-1) == 0) {
      82           0 :                                 return 1;
      83             :                         }
      84             :                         
      85           0 :                         zend_hash_move_forward(Z_ARRVAL_P(stream->wrapperdata));
      86             :                 }
      87             :         }
      88           0 :         return 0;
      89             : }
      90             : 
      91          27 : static int handle_ssl_error(php_stream *stream, int nr_bytes, zend_bool is_init TSRMLS_DC)
      92             : {
      93          27 :         php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
      94          27 :         int err = SSL_get_error(sslsock->ssl_handle, nr_bytes);
      95             :         char esbuf[512];
      96          27 :         smart_str ebuf = {0};
      97             :         unsigned long ecode;
      98          27 :         int retry = 1;
      99             : 
     100          27 :         switch(err) {
     101             :                 case SSL_ERROR_ZERO_RETURN:
     102             :                         /* SSL terminated (but socket may still be active) */
     103           0 :                         retry = 0;
     104           0 :                         break;
     105             :                 case SSL_ERROR_WANT_READ:
     106             :                 case SSL_ERROR_WANT_WRITE:
     107             :                         /* re-negotiation, or perhaps the SSL layer needs more
     108             :                          * packets: retry in next iteration */
     109          27 :                         errno = EAGAIN;
     110          27 :                         retry = is_init ? 1 : sslsock->s.is_blocked;
     111          27 :                         break;
     112             :                 case SSL_ERROR_SYSCALL:
     113           0 :                         if (ERR_peek_error() == 0) {
     114           0 :                                 if (nr_bytes == 0) {
     115           0 :                                         if (!is_http_stream_talking_to_iis(stream TSRMLS_CC) && ERR_get_error() != 0) {
     116           0 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING,
     117             :                                                                 "SSL: fatal protocol error");
     118             :                                         }
     119           0 :                                         SSL_set_shutdown(sslsock->ssl_handle, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
     120           0 :                                         stream->eof = 1;
     121           0 :                                         retry = 0;
     122             :                                 } else {
     123           0 :                                         char *estr = php_socket_strerror(php_socket_errno(), NULL, 0);
     124             : 
     125           0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING,
     126             :                                                         "SSL: %s", estr);
     127             : 
     128           0 :                                         efree(estr);
     129           0 :                                         retry = 0;
     130             :                                 }
     131           0 :                                 break;
     132             :                         }
     133             : 
     134             :                         
     135             :                         /* fall through */
     136             :                 default:
     137             :                         /* some other error */
     138           0 :                         ecode = ERR_get_error();
     139             : 
     140           0 :                         switch (ERR_GET_REASON(ecode)) {
     141             :                                 case SSL_R_NO_SHARED_CIPHER:
     142           0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL_R_NO_SHARED_CIPHER: no suitable shared cipher could be used.  This could be because the server is missing an SSL certificate (local_cert context option)");
     143           0 :                                         retry = 0;
     144           0 :                                         break;
     145             : 
     146             :                                 default:
     147             :                                         do {
     148             :                                                 /* NULL is automatically added */
     149           0 :                                                 ERR_error_string_n(ecode, esbuf, sizeof(esbuf));
     150           0 :                                                 if (ebuf.c) {
     151           0 :                                                         smart_str_appendc(&ebuf, '\n');
     152             :                                                 }
     153           0 :                                                 smart_str_appends(&ebuf, esbuf);
     154           0 :                                         } while ((ecode = ERR_get_error()) != 0);
     155             : 
     156           0 :                                         smart_str_0(&ebuf);
     157             : 
     158           0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING,
     159             :                                                         "SSL operation failed with code %d. %s%s",
     160             :                                                         err,
     161           0 :                                                         ebuf.c ? "OpenSSL Error messages:\n" : "",
     162           0 :                                                         ebuf.c ? ebuf.c : "");
     163           0 :                                         if (ebuf.c) {
     164           0 :                                                 smart_str_free(&ebuf);
     165             :                                         }
     166             :                         }
     167             :                                 
     168           0 :                         retry = 0;
     169           0 :                         errno = 0;
     170             :         }
     171          27 :         return retry;
     172             : }
     173             : 
     174             : 
     175         416 : static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
     176             : {
     177         416 :         php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
     178             :         int didwrite;
     179             :         
     180         416 :         if (sslsock->ssl_active) {
     181          12 :                 int retry = 1;
     182             : 
     183             :                 do {
     184          12 :                         didwrite = SSL_write(sslsock->ssl_handle, buf, count);
     185             : 
     186          12 :                         if (didwrite <= 0) {
     187           0 :                                 retry = handle_ssl_error(stream, didwrite, 0 TSRMLS_CC);
     188             :                         } else {
     189          12 :                                 break;
     190             :                         }
     191           0 :                 } while(retry);
     192             : 
     193          12 :                 if (didwrite > 0) {
     194          12 :                         php_stream_notify_progress_increment(stream->context, didwrite, 0);
     195             :                 }
     196             :         } else {
     197         404 :                 didwrite = php_stream_socket_ops.write(stream, buf, count TSRMLS_CC);
     198             :         }
     199             : 
     200         416 :         if (didwrite < 0) {
     201           0 :                 didwrite = 0;
     202             :         }
     203             :         
     204         416 :         return didwrite;
     205             : }
     206             : 
     207           9 : static void php_openssl_stream_wait_for_data(php_netstream_data_t *sock)
     208             : {
     209             :         int retval;
     210             :         struct timeval *ptimeout;
     211             : 
     212           9 :         if (sock->socket == -1) {
     213           0 :                 return;
     214             :         }
     215             :         
     216           9 :         sock->timeout_event = 0;
     217             : 
     218           9 :         if (sock->timeout.tv_sec == -1)
     219           0 :                 ptimeout = NULL;
     220             :         else
     221           9 :                 ptimeout = &sock->timeout;
     222             : 
     223             :         while(1) {
     224           9 :                 retval = php_pollfd_for(sock->socket, PHP_POLLREADABLE, ptimeout);
     225             : 
     226           9 :                 if (retval == 0)
     227           0 :                         sock->timeout_event = 1;
     228             : 
     229           9 :                 if (retval >= 0)
     230           9 :                         break;
     231             : 
     232           0 :                 if (php_socket_errno() != EINTR)
     233           0 :                         break;
     234           0 :         }
     235             : }
     236             : 
     237         239 : static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
     238             : {
     239         239 :         php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
     240             :         php_netstream_data_t *sock;
     241         239 :         int nr_bytes = 0;
     242             : 
     243         239 :         if (sslsock->ssl_active) {
     244          10 :                 int retry = 1;
     245          10 :                 sock = (php_netstream_data_t*)stream->abstract;
     246             : 
     247             :                 /* The SSL_read() function will block indefinitely waiting for data on a blocking
     248             :                    socket. If we don't poll for readability first this operation has the potential
     249             :                    to hang forever. To avoid this scenario we poll with a timeout before performing
     250             :                    the actual read. If it times out we're finished.
     251             :                 */
     252          10 :                 if (sock->is_blocked) {
     253           9 :                         php_openssl_stream_wait_for_data(sock);
     254           9 :                         if (sock->timeout_event) {
     255           0 :                                 stream->eof = 1;
     256           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL read operation timed out");
     257           0 :                                 return nr_bytes;
     258             :                         }
     259             :                 }
     260             : 
     261             :                 do {
     262          10 :                         nr_bytes = SSL_read(sslsock->ssl_handle, buf, count);
     263             : 
     264          10 :                         if (nr_bytes <= 0) {
     265           0 :                                 retry = handle_ssl_error(stream, nr_bytes, 0 TSRMLS_CC);
     266           0 :                                 stream->eof = (retry == 0 && errno != EAGAIN && !SSL_pending(sslsock->ssl_handle));
     267             :                                 
     268             :                         } else {
     269             :                                 /* we got the data */
     270          10 :                                 break;
     271             :                         }
     272           0 :                 } while (retry);
     273             : 
     274          10 :                 if (nr_bytes > 0) {
     275          10 :                         php_stream_notify_progress_increment(stream->context, nr_bytes, 0);
     276             :                 }
     277             :         }
     278             :         else
     279             :         {
     280         229 :                 nr_bytes = php_stream_socket_ops.read(stream, buf, count TSRMLS_CC);
     281             :         }
     282             : 
     283         239 :         if (nr_bytes < 0) {
     284           0 :                 nr_bytes = 0;
     285             :         }
     286             : 
     287         239 :         return nr_bytes;
     288             : }
     289             : 
     290             : 
     291        1061 : static int php_openssl_sockop_close(php_stream *stream, int close_handle TSRMLS_DC)
     292             : {
     293        1061 :         php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
     294             : #ifdef PHP_WIN32
     295             :         int n;
     296             : #endif
     297        1061 :         if (close_handle) {
     298        1061 :                 if (sslsock->ssl_active) {
     299          15 :                         SSL_shutdown(sslsock->ssl_handle);
     300          15 :                         sslsock->ssl_active = 0;
     301             :                 }
     302        1061 :                 if (sslsock->ssl_handle) {
     303          16 :                         SSL_free(sslsock->ssl_handle);
     304          16 :                         sslsock->ssl_handle = NULL;
     305             :                 }
     306        1061 :                 if (sslsock->ctx) {
     307          16 :                         SSL_CTX_free(sslsock->ctx);
     308          16 :                         sslsock->ctx = NULL;
     309             :                 }
     310             : #ifdef PHP_WIN32
     311             :                 if (sslsock->s.socket == -1)
     312             :                         sslsock->s.socket = SOCK_ERR;
     313             : #endif
     314        1061 :                 if (sslsock->s.socket != SOCK_ERR) {
     315             : #ifdef PHP_WIN32
     316             :                         /* prevent more data from coming in */
     317             :                         shutdown(sslsock->s.socket, SHUT_RD);
     318             : 
     319             :                         /* try to make sure that the OS sends all data before we close the connection.
     320             :                          * Essentially, we are waiting for the socket to become writeable, which means
     321             :                          * that all pending data has been sent.
     322             :                          * We use a small timeout which should encourage the OS to send the data,
     323             :                          * but at the same time avoid hanging indefinitely.
     324             :                          * */
     325             :                         do {
     326             :                                 n = php_pollfd_for_ms(sslsock->s.socket, POLLOUT, 500);
     327             :                         } while (n == -1 && php_socket_errno() == EINTR);
     328             : #endif
     329         209 :                         closesocket(sslsock->s.socket);
     330         209 :                         sslsock->s.socket = SOCK_ERR;
     331             :                 }
     332             :         }
     333             : 
     334        1061 :         if (sslsock->sni) {
     335        1002 :                 pefree(sslsock->sni, php_stream_is_persistent(stream));
     336             :         }
     337        1061 :         pefree(sslsock, php_stream_is_persistent(stream));
     338             :         
     339        1061 :         return 0;
     340             : }
     341             : 
     342        1061 : static int php_openssl_sockop_flush(php_stream *stream TSRMLS_DC)
     343             : {
     344        1061 :         return php_stream_socket_ops.flush(stream TSRMLS_CC);
     345             : }
     346             : 
     347           2 : static int php_openssl_sockop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
     348             : {
     349           2 :         return php_stream_socket_ops.stat(stream, ssb TSRMLS_CC);
     350             : }
     351             : 
     352             : 
     353          16 : static inline int php_openssl_setup_crypto(php_stream *stream,
     354             :                 php_openssl_netstream_data_t *sslsock,
     355             :                 php_stream_xport_crypto_param *cparam
     356             :                 TSRMLS_DC)
     357             : {
     358             :         SSL_METHOD *method;
     359          16 :         long ssl_ctx_options = SSL_OP_ALL;
     360             :         
     361          16 :         if (sslsock->ssl_handle) {
     362           0 :                 if (sslsock->s.is_blocked) {
     363           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL/TLS already set-up for this stream");
     364           0 :                         return -1;
     365             :                 } else {
     366           0 :                         return 0;
     367             :                 }
     368             :         }
     369             : 
     370             :         /* need to do slightly different things, based on client/server method,
     371             :          * so lets remember which method was selected */
     372             : 
     373          16 :         switch (cparam->inputs.method) {
     374             :                 case STREAM_CRYPTO_METHOD_SSLv23_CLIENT:
     375           7 :                         sslsock->is_client = 1;
     376           7 :                         method = SSLv23_client_method();
     377           7 :                         break;
     378             :                 case STREAM_CRYPTO_METHOD_SSLv2_CLIENT:
     379             : #ifdef OPENSSL_NO_SSL2
     380             :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSLv2 support is not compiled into the OpenSSL library PHP is linked against");
     381             :                         return -1;
     382             : #else
     383           0 :                         sslsock->is_client = 1;
     384           0 :                         method = SSLv2_client_method();
     385           0 :                         break;
     386             : #endif
     387             :                 case STREAM_CRYPTO_METHOD_SSLv3_CLIENT:
     388           0 :                         sslsock->is_client = 1;
     389           0 :                         method = SSLv3_client_method();
     390           0 :                         break;
     391             :                 case STREAM_CRYPTO_METHOD_TLS_CLIENT:
     392           5 :                         sslsock->is_client = 1;
     393           5 :                         method = TLSv1_client_method();
     394           5 :                         break;
     395             :                 case STREAM_CRYPTO_METHOD_SSLv23_SERVER:
     396           4 :                         sslsock->is_client = 0;
     397           4 :                         method = SSLv23_server_method();
     398           4 :                         break;
     399             :                 case STREAM_CRYPTO_METHOD_SSLv3_SERVER:
     400           0 :                         sslsock->is_client = 0;
     401           0 :                         method = SSLv3_server_method();
     402           0 :                         break;
     403             :                 case STREAM_CRYPTO_METHOD_SSLv2_SERVER:
     404             : #ifdef OPENSSL_NO_SSL2
     405             :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSLv2 support is not compiled into the OpenSSL library PHP is linked against");
     406             :                         return -1;
     407             : #else
     408           0 :                         sslsock->is_client = 0;
     409           0 :                         method = SSLv2_server_method();
     410           0 :                         break;
     411             : #endif
     412             :                 case STREAM_CRYPTO_METHOD_TLS_SERVER:
     413           0 :                         sslsock->is_client = 0;
     414           0 :                         method = TLSv1_server_method();
     415           0 :                         break;
     416             :                 default:
     417           0 :                         return -1;
     418             : 
     419             :         }
     420             : 
     421          16 :         sslsock->ctx = SSL_CTX_new(method);
     422          16 :         if (sslsock->ctx == NULL) {
     423           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create an SSL context");
     424           0 :                 return -1;
     425             :         }
     426             : 
     427             : #if OPENSSL_VERSION_NUMBER >= 0x0090605fL
     428          16 :         ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
     429             : #endif
     430          16 :         SSL_CTX_set_options(sslsock->ctx, ssl_ctx_options);
     431             : 
     432             : #if OPENSSL_VERSION_NUMBER >= 0x0090806fL
     433             :         {
     434             :                 zval **val;
     435             : 
     436          31 :                 if (stream->context && SUCCESS == php_stream_context_get_option(
     437          15 :                                         stream->context, "ssl", "no_ticket", &val) && 
     438           0 :                                 zval_is_true(*val)) {
     439           0 :                         SSL_CTX_set_options(sslsock->ctx, SSL_OP_NO_TICKET);
     440             :                 }
     441             :         }
     442             : #endif
     443             : 
     444             : #if OPENSSL_VERSION_NUMBER >= 0x10000000L
     445             :         {
     446             :                 zval **val;
     447             : 
     448          31 :                 if (stream->context && SUCCESS == php_stream_context_get_option(
     449          15 :                                         stream->context, "ssl", "disable_compression", &val) &&
     450           0 :                                 zval_is_true(*val)) {
     451           0 :                         SSL_CTX_set_options(sslsock->ctx, SSL_OP_NO_COMPRESSION);
     452             :                 }
     453             :         }
     454             : #endif
     455             : 
     456          16 :         sslsock->ssl_handle = php_SSL_new_from_context(sslsock->ctx, stream TSRMLS_CC);
     457          16 :         if (sslsock->ssl_handle == NULL) {
     458           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create an SSL handle");
     459           0 :                 SSL_CTX_free(sslsock->ctx);
     460           0 :                 sslsock->ctx = NULL;
     461           0 :                 return -1;
     462             :         }
     463             : 
     464          16 :         if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) {
     465           0 :                 handle_ssl_error(stream, 0, 1 TSRMLS_CC);
     466             :         }
     467             : 
     468          16 :         if (cparam->inputs.session) {
     469           0 :                 if (cparam->inputs.session->ops != &php_openssl_socket_ops) {
     470           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied session stream must be an SSL enabled stream");
     471           0 :                 } else if (((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle == NULL) {
     472           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied SSL session stream is not initialized");
     473             :                 } else {
     474           0 :                         SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle);
     475             :                 }
     476             :         }
     477          16 :         return 0;
     478             : }
     479             : 
     480          16 : static inline int php_openssl_enable_crypto(php_stream *stream,
     481             :                 php_openssl_netstream_data_t *sslsock,
     482             :                 php_stream_xport_crypto_param *cparam
     483             :                 TSRMLS_DC)
     484             : {
     485          16 :         int n, retry = 1;
     486             : 
     487          16 :         if (cparam->inputs.activate && !sslsock->ssl_active) {
     488             :                 struct timeval  start_time,
     489             :                                                 *timeout;
     490          16 :                 int                             blocked         = sslsock->s.is_blocked,
     491          16 :                                                 has_timeout = 0;
     492             : 
     493             : #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
     494          16 :                 if (sslsock->is_client && sslsock->sni) {
     495          10 :                         SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->sni);
     496             :                 }
     497             : #endif
     498             : 
     499          16 :                 if (!sslsock->state_set) {
     500          16 :                         if (sslsock->is_client) {
     501          12 :                                 SSL_set_connect_state(sslsock->ssl_handle);
     502             :                         } else {
     503           4 :                                 SSL_set_accept_state(sslsock->ssl_handle);
     504             :                         }
     505          16 :                         sslsock->state_set = 1;
     506             :                 }
     507             :         
     508          16 :                 if (SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC)) {
     509          16 :                         sslsock->s.is_blocked = 0;
     510             :                 }
     511             :                 
     512          16 :                 timeout = sslsock->is_client ? &sslsock->connect_timeout : &sslsock->s.timeout;
     513          16 :                 has_timeout = !sslsock->s.is_blocked && (timeout->tv_sec || timeout->tv_usec);
     514             :                 /* gettimeofday is not monotonic; using it here is not strictly correct */
     515          16 :                 if (has_timeout) {
     516          16 :                         gettimeofday(&start_time, NULL);
     517             :                 }
     518             :                 
     519             :                 do {
     520             :                         struct timeval  cur_time,
     521          43 :                                                         elapsed_time = {0};
     522             :                         
     523          43 :                         if (sslsock->is_client) {
     524          35 :                                 n = SSL_connect(sslsock->ssl_handle);
     525             :                         } else {
     526           8 :                                 n = SSL_accept(sslsock->ssl_handle);
     527             :                         }
     528             : 
     529          43 :                         if (has_timeout) {
     530          43 :                                 gettimeofday(&cur_time, NULL);
     531          43 :                                 elapsed_time.tv_sec  = cur_time.tv_sec  - start_time.tv_sec;
     532          43 :                                 elapsed_time.tv_usec = cur_time.tv_usec - start_time.tv_usec;
     533          43 :                                 if (cur_time.tv_usec < start_time.tv_usec) {
     534          16 :                                         elapsed_time.tv_sec  -= 1L;
     535          16 :                                         elapsed_time.tv_usec += 1000000L;
     536             :                                 }
     537             :                         
     538          87 :                                 if (elapsed_time.tv_sec > timeout->tv_sec ||
     539          43 :                                                 (elapsed_time.tv_sec == timeout->tv_sec &&
     540           1 :                                                 elapsed_time.tv_usec > timeout->tv_usec)) {
     541           1 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL: crypto enabling timeout");
     542           1 :                                         return -1;
     543             :                                 }
     544             :                         }
     545             : 
     546          42 :                         if (n <= 0) {
     547             :                                 /* in case of SSL_ERROR_WANT_READ/WRITE, do not retry in non-blocking mode */
     548          27 :                                 retry = handle_ssl_error(stream, n, blocked TSRMLS_CC);
     549          27 :                                 if (retry) {
     550             :                                         /* wait until something interesting happens in the socket. It may be a
     551             :                                          * timeout. Also consider the unlikely of possibility of a write block  */
     552          27 :                                         int err = SSL_get_error(sslsock->ssl_handle, n);
     553             :                                         struct timeval left_time;
     554             :                                         
     555          27 :                                         if (has_timeout) {
     556          27 :                                                 left_time.tv_sec  = timeout->tv_sec  - elapsed_time.tv_sec;
     557          27 :                                                 left_time.tv_usec =     timeout->tv_usec - elapsed_time.tv_usec;
     558          27 :                                                 if (timeout->tv_usec < elapsed_time.tv_usec) {
     559          27 :                                                         left_time.tv_sec  -= 1L;
     560          27 :                                                         left_time.tv_usec += 1000000L;
     561             :                                                 }
     562             :                                         }
     563          27 :                                         php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
     564             :                                                 (POLLIN|POLLPRI) : POLLOUT, has_timeout ? &left_time : NULL);
     565             :                                 }
     566             :                         } else {
     567          15 :                                 retry = 0;
     568             :                         }
     569          42 :                 } while (retry);
     570             : 
     571          15 :                 if (sslsock->s.is_blocked != blocked && SUCCESS == php_set_sock_blocking(sslsock->s.socket, blocked TSRMLS_CC)) {
     572          15 :                         sslsock->s.is_blocked = blocked;
     573             :                 }
     574             : 
     575          15 :                 if (n == 1) {
     576             :                         X509 *peer_cert;
     577             : 
     578          15 :                         peer_cert = SSL_get_peer_certificate(sslsock->ssl_handle);
     579             : 
     580          15 :                         if (FAILURE == php_openssl_apply_verification_policy(sslsock->ssl_handle, peer_cert, stream TSRMLS_CC)) {
     581           0 :                                 SSL_shutdown(sslsock->ssl_handle);
     582           0 :                                 n = -1;
     583             :                         } else {        
     584          15 :                                 sslsock->ssl_active = 1;
     585             : 
     586             :                                 /* allow the script to capture the peer cert
     587             :                                  * and/or the certificate chain */
     588          15 :                                 if (stream->context) {
     589             :                                         zval **val, *zcert;
     590             : 
     591          23 :                                         if (SUCCESS == php_stream_context_get_option(
     592             :                                                                 stream->context, "ssl",
     593          14 :                                                                 "capture_peer_cert", &val) &&
     594           9 :                                                         zval_is_true(*val)) {
     595           9 :                                                 MAKE_STD_ZVAL(zcert);
     596           9 :                                                 ZVAL_RESOURCE(zcert, zend_list_insert(peer_cert, 
     597             :                                                                         php_openssl_get_x509_list_id() TSRMLS_CC));
     598           9 :                                                 php_stream_context_set_option(stream->context,
     599             :                                                                 "ssl", "peer_certificate",
     600             :                                                                 zcert);
     601           9 :                                                 peer_cert = NULL;
     602           9 :                                                 FREE_ZVAL(zcert);
     603             :                                         }
     604             : 
     605          14 :                                         if (SUCCESS == php_stream_context_get_option(
     606             :                                                                 stream->context, "ssl",
     607          14 :                                                                 "capture_peer_cert_chain", &val) &&
     608           0 :                                                         zval_is_true(*val)) {
     609             :                                                 zval *arr;
     610             :                                                 STACK_OF(X509) *chain;
     611             : 
     612           0 :                                                 MAKE_STD_ZVAL(arr);
     613           0 :                                                 chain = SSL_get_peer_cert_chain(
     614           0 :                                                                         sslsock->ssl_handle);
     615             : 
     616           0 :                                                 if (chain && sk_X509_num(chain) > 0) {
     617             :                                                         int i;
     618           0 :                                                         array_init(arr);
     619             : 
     620           0 :                                                         for (i = 0; i < sk_X509_num(chain); i++) {
     621           0 :                                                                 X509 *mycert = X509_dup(
     622           0 :                                                                                 sk_X509_value(chain, i));
     623           0 :                                                                 MAKE_STD_ZVAL(zcert);
     624           0 :                                                                 ZVAL_RESOURCE(zcert,
     625             :                                                                                 zend_list_insert(mycert,
     626             :                                                                                         php_openssl_get_x509_list_id() TSRMLS_CC));
     627           0 :                                                                 add_next_index_zval(arr, zcert);
     628             :                                                         }
     629             : 
     630             :                                                 } else {
     631           0 :                                                         ZVAL_NULL(arr);
     632             :                                                 }
     633             : 
     634           0 :                                                 php_stream_context_set_option(stream->context,
     635             :                                                                 "ssl", "peer_certificate_chain",
     636             :                                                                 arr);
     637             :                                                 zval_dtor(arr);
     638           0 :                                                 efree(arr);
     639             :                                         }
     640             :                                 }
     641             :                         }
     642             : 
     643          15 :                         if (peer_cert) {
     644           2 :                                 X509_free(peer_cert);
     645             :                         }
     646             :                 } else  {
     647           0 :                         n = errno == EAGAIN ? 0 : -1;
     648             :                 }
     649             : 
     650          15 :                 return n;
     651             : 
     652           0 :         } else if (!cparam->inputs.activate && sslsock->ssl_active) {
     653             :                 /* deactivate - common for server/client */
     654           0 :                 SSL_shutdown(sslsock->ssl_handle);
     655           0 :                 sslsock->ssl_active = 0;
     656             :         }
     657           0 :         return -1;
     658             : }
     659             : 
     660          44 : static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_netstream_data_t *sock,
     661             :                 php_stream_xport_param *xparam STREAMS_DC TSRMLS_DC)
     662             : {
     663             :         int clisock;
     664             : 
     665          44 :         xparam->outputs.client = NULL;
     666             : 
     667         264 :         clisock = php_network_accept_incoming(sock->s.socket,
     668          44 :                         xparam->want_textaddr ? &xparam->outputs.textaddr : NULL,
     669          44 :                         xparam->want_textaddr ? &xparam->outputs.textaddrlen : NULL,
     670          44 :                         xparam->want_addr ? &xparam->outputs.addr : NULL,
     671          44 :                         xparam->want_addr ? &xparam->outputs.addrlen : NULL,
     672             :                         xparam->inputs.timeout,
     673          44 :                         xparam->want_errortext ? &xparam->outputs.error_text : NULL,
     674             :                         &xparam->outputs.error_code
     675             :                         TSRMLS_CC);
     676             : 
     677          44 :         if (clisock >= 0) {
     678             :                 php_openssl_netstream_data_t *clisockdata;
     679             : 
     680          44 :                 clisockdata = emalloc(sizeof(*clisockdata));
     681             : 
     682          44 :                 if (clisockdata == NULL) {
     683           0 :                         closesocket(clisock);
     684             :                         /* technically a fatal error */
     685             :                 } else {
     686             :                         /* copy underlying tcp fields */
     687          44 :                         memset(clisockdata, 0, sizeof(*clisockdata));
     688          44 :                         memcpy(clisockdata, sock, sizeof(clisockdata->s));
     689             : 
     690          44 :                         clisockdata->s.socket = clisock;
     691             :                         
     692          44 :                         xparam->outputs.client = php_stream_alloc_rel(stream->ops, clisockdata, NULL, "r+");
     693          44 :                         if (xparam->outputs.client) {
     694          44 :                                 xparam->outputs.client->context = stream->context;
     695          44 :                                 if (stream->context) {
     696          44 :                                         zend_list_addref(stream->context->rsrc_id);
     697             :                                 }
     698             :                         }
     699             :                 }
     700             : 
     701          44 :                 if (xparam->outputs.client && sock->enable_on_connect) {
     702             :                         /* apply crypto */
     703           3 :                         switch (sock->method) {
     704             :                                 case STREAM_CRYPTO_METHOD_SSLv23_CLIENT:
     705           3 :                                         sock->method = STREAM_CRYPTO_METHOD_SSLv23_SERVER;
     706           3 :                                         break;
     707             :                                 case STREAM_CRYPTO_METHOD_SSLv2_CLIENT:
     708           0 :                                         sock->method = STREAM_CRYPTO_METHOD_SSLv2_SERVER;
     709           0 :                                         break;
     710             :                                 case STREAM_CRYPTO_METHOD_SSLv3_CLIENT:
     711           0 :                                         sock->method = STREAM_CRYPTO_METHOD_SSLv3_SERVER;
     712           0 :                                         break;
     713             :                                 case STREAM_CRYPTO_METHOD_TLS_CLIENT:
     714           0 :                                         sock->method = STREAM_CRYPTO_METHOD_TLS_SERVER;
     715             :                                         break;
     716             :                                 default:
     717             :                                         break;
     718             :                         }
     719             : 
     720           3 :                         clisockdata->method = sock->method;
     721             : 
     722           6 :                         if (php_stream_xport_crypto_setup(xparam->outputs.client, clisockdata->method,
     723           3 :                                         NULL TSRMLS_CC) < 0 || php_stream_xport_crypto_enable(
     724           3 :                                         xparam->outputs.client, 1 TSRMLS_CC) < 0) {
     725           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to enable crypto");
     726             : 
     727           0 :                                 php_stream_close(xparam->outputs.client);
     728           0 :                                 xparam->outputs.client = NULL;
     729           0 :                                 xparam->outputs.returncode = -1;
     730             :                         }
     731             :                 }
     732             :         }
     733             :         
     734          44 :         return xparam->outputs.client == NULL ? -1 : 0;
     735             : }
     736        1169 : static int php_openssl_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
     737             : {
     738        1169 :         php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
     739        1169 :         php_stream_xport_crypto_param *cparam = (php_stream_xport_crypto_param *)ptrparam;
     740        1169 :         php_stream_xport_param *xparam = (php_stream_xport_param *)ptrparam;
     741             : 
     742        1169 :         switch (option) {
     743             :                 case PHP_STREAM_OPTION_CHECK_LIVENESS:
     744             :                         {
     745             :                                 struct timeval tv;
     746             :                                 char buf;
     747           3 :                                 int alive = 1;
     748             : 
     749           3 :                                 if (value == -1) {
     750           0 :                                         if (sslsock->s.timeout.tv_sec == -1) {
     751           0 :                                                 tv.tv_sec = FG(default_socket_timeout);
     752           0 :                                                 tv.tv_usec = 0;
     753             :                                         } else {
     754           0 :                                                 tv = sslsock->connect_timeout;
     755             :                                         }
     756             :                                 } else {
     757           3 :                                         tv.tv_sec = value;
     758           3 :                                         tv.tv_usec = 0;
     759             :                                 }
     760             : 
     761           3 :                                 if (sslsock->s.socket == -1) {
     762           0 :                                         alive = 0;
     763           3 :                                 } else if (php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) {
     764           3 :                                         if (sslsock->ssl_active) {
     765             :                                                 int n;
     766             : 
     767             :                                                 do {
     768           0 :                                                         n = SSL_peek(sslsock->ssl_handle, &buf, sizeof(buf));
     769           0 :                                                         if (n <= 0) {
     770           0 :                                                                 int err = SSL_get_error(sslsock->ssl_handle, n);
     771             : 
     772           0 :                                                                 if (err == SSL_ERROR_SYSCALL) {
     773           0 :                                                                         alive = php_socket_errno() == EAGAIN;
     774           0 :                                                                         break;
     775             :                                                                 }
     776             : 
     777           0 :                                                                 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
     778             :                                                                         /* re-negotiate */
     779           0 :                                                                         continue;
     780             :                                                                 }
     781             : 
     782             :                                                                 /* any other problem is a fatal error */
     783           0 :                                                                 alive = 0;
     784             :                                                         }
     785             :                                                         /* either peek succeeded or there was an error; we
     786             :                                                          * have set the alive flag appropriately */
     787           0 :                                                         break;
     788           0 :                                                 } while (1);
     789           3 :                                         } else if (0 == recv(sslsock->s.socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) {
     790           3 :                                                 alive = 0;
     791             :                                         }
     792             :                                 }
     793           3 :                                 return alive ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
     794             :                         }
     795             :                         
     796             :                 case PHP_STREAM_OPTION_CRYPTO_API:
     797             : 
     798          32 :                         switch(cparam->op) {
     799             : 
     800             :                                 case STREAM_XPORT_CRYPTO_OP_SETUP:
     801          16 :                                         cparam->outputs.returncode = php_openssl_setup_crypto(stream, sslsock, cparam TSRMLS_CC);
     802          16 :                                         return PHP_STREAM_OPTION_RETURN_OK;
     803             :                                         break;
     804             :                                 case STREAM_XPORT_CRYPTO_OP_ENABLE:
     805          16 :                                         cparam->outputs.returncode = php_openssl_enable_crypto(stream, sslsock, cparam TSRMLS_CC);
     806          16 :                                         return PHP_STREAM_OPTION_RETURN_OK;
     807             :                                         break;
     808             :                                 default:
     809             :                                         /* fall through */
     810             :                                         break;
     811             :                         }
     812             : 
     813           0 :                         break;
     814             : 
     815             :                 case PHP_STREAM_OPTION_XPORT_API:
     816        1111 :                         switch(xparam->op) {
     817             : 
     818             :                                 case STREAM_XPORT_OP_CONNECT:
     819             :                                 case STREAM_XPORT_OP_CONNECT_ASYNC:
     820             :                                         /* TODO: Async connects need to check the enable_on_connect option when
     821             :                                          * we notice that the connect has actually been established */
     822         903 :                                         php_stream_socket_ops.set_option(stream, option, value, ptrparam TSRMLS_CC);
     823             : 
     824         913 :                                         if ((sslsock->enable_on_connect) &&
     825           7 :                                                 ((xparam->outputs.returncode == 0) ||
     826           1 :                                                 (xparam->op == STREAM_XPORT_OP_CONNECT_ASYNC && 
     827           2 :                                                 xparam->outputs.returncode == 1 && xparam->outputs.error_code == EINPROGRESS)))
     828             :                                         {
     829          14 :                                                 if (php_stream_xport_crypto_setup(stream, sslsock->method, NULL TSRMLS_CC) < 0 ||
     830           7 :                                                                 php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0) {
     831           1 :                                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to enable crypto");
     832           1 :                                                         xparam->outputs.returncode = -1;
     833             :                                                 }
     834             :                                         }
     835         903 :                                         return PHP_STREAM_OPTION_RETURN_OK;
     836             : 
     837             :                                 case STREAM_XPORT_OP_ACCEPT:
     838             :                                         /* we need to copy the additional fields that the underlying tcp transport
     839             :                                          * doesn't know about */
     840          44 :                                         xparam->outputs.returncode = php_openssl_tcp_sockop_accept(stream, sslsock, xparam STREAMS_CC TSRMLS_CC);
     841             : 
     842             :                                         
     843          44 :                                         return PHP_STREAM_OPTION_RETURN_OK;
     844             : 
     845             :                                 default:
     846             :                                         /* fall through */
     847             :                                         break;
     848             :                         }
     849             :         }
     850             : 
     851         187 :         return php_stream_socket_ops.set_option(stream, option, value, ptrparam TSRMLS_CC);
     852             : }
     853             : 
     854           6 : static int php_openssl_sockop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
     855             : {
     856           6 :         php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
     857             : 
     858           6 :         switch(castas)  {
     859             :                 case PHP_STREAM_AS_STDIO:
     860           0 :                         if (sslsock->ssl_active) {
     861           0 :                                 return FAILURE;
     862             :                         }
     863           0 :                         if (ret)        {
     864           0 :                                 *ret = fdopen(sslsock->s.socket, stream->mode);
     865           0 :                                 if (*ret) {
     866           0 :                                         return SUCCESS;
     867             :                                 }
     868           0 :                                 return FAILURE;
     869             :                         }
     870           0 :                         return SUCCESS;
     871             : 
     872             :                 case PHP_STREAM_AS_FD_FOR_SELECT:
     873           6 :                         if (ret) {
     874           6 :                                 if (sslsock->ssl_active) {
     875             :                                         /* OpenSSL has an internal buffer which select() cannot see. If we don't
     876             :                                            fetch it into the stream's buffer, no activity will be reported on the
     877             :                                            stream even though there is data waiting to be read - but we only fetch
     878             :                                            the number of bytes OpenSSL has ready to give us since we weren't asked
     879             :                                            for any data at this stage. This is only likely to cause issues with
     880             :                                            non-blocking streams, but it's harmless to always do it. */
     881             :                                         int bytes;
     882          12 :                                         while ((bytes = SSL_pending(sslsock->ssl_handle)) > 0) {
     883           0 :                                                 php_stream_fill_read_buffer(stream, (size_t)bytes);
     884             :                                         }
     885             :                                 }
     886             : 
     887           6 :                                 *(int *)ret = sslsock->s.socket;
     888             :                         }
     889           6 :                         return SUCCESS;
     890             : 
     891             :                 case PHP_STREAM_AS_FD:
     892             :                 case PHP_STREAM_AS_SOCKETD:
     893           0 :                         if (sslsock->ssl_active) {
     894           0 :                                 return FAILURE;
     895             :                         }
     896           0 :                         if (ret) {
     897           0 :                                 *(int *)ret = sslsock->s.socket;
     898             :                         }
     899           0 :                         return SUCCESS;
     900             :                 default:
     901           0 :                         return FAILURE;
     902             :         }
     903             : }
     904             : 
     905             : php_stream_ops php_openssl_socket_ops = {
     906             :         php_openssl_sockop_write, php_openssl_sockop_read,
     907             :         php_openssl_sockop_close, php_openssl_sockop_flush,
     908             :         "tcp_socket/ssl",
     909             :         NULL, /* seek */
     910             :         php_openssl_sockop_cast,
     911             :         php_openssl_sockop_stat,
     912             :         php_openssl_sockop_set_option,
     913             : };
     914             : 
     915         985 : static char * get_sni(php_stream_context *ctx, char *resourcename, long resourcenamelen, int is_persistent TSRMLS_DC) {
     916             : 
     917             :         php_url *url;
     918             : 
     919         985 :         if (ctx) {
     920         123 :                 zval **val = NULL;
     921             : 
     922         123 :                 if (php_stream_context_get_option(ctx, "ssl", "SNI_enabled", &val) == SUCCESS && !zend_is_true(*val)) {
     923           2 :                         return NULL;
     924             :                 }
     925         121 :                 if (php_stream_context_get_option(ctx, "ssl", "SNI_server_name", &val) == SUCCESS) {
     926           3 :                         convert_to_string_ex(val);
     927           3 :                         return pestrdup(Z_STRVAL_PP(val), is_persistent);
     928             :                 }
     929             :         }
     930             : 
     931         980 :         if (!resourcename) {
     932           0 :                 return NULL;
     933             :         }
     934             : 
     935         980 :         url = php_url_parse_ex(resourcename, resourcenamelen);
     936         980 :         if (!url) {
     937           0 :                 return NULL;
     938             :         }
     939             : 
     940         980 :         if (url->host) {
     941         967 :                 const char * host = url->host;
     942         967 :                 char * sni = NULL;
     943         967 :                 size_t len = strlen(host);
     944             : 
     945             :                 /* skip trailing dots */
     946        1934 :                 while (len && host[len-1] == '.') {
     947           0 :                         --len;
     948             :                 }
     949             : 
     950         967 :                 if (len) {
     951         967 :                         sni = pestrndup(host, len, is_persistent);
     952             :                 }
     953             : 
     954         967 :                 php_url_free(url);
     955         967 :                 return sni;
     956             :         }
     957             : 
     958          13 :         php_url_free(url);
     959          13 :         return NULL;
     960             : }
     961             : 
     962         985 : php_stream *php_openssl_ssl_socket_factory(const char *proto, long protolen,
     963             :                 char *resourcename, long resourcenamelen,
     964             :                 const char *persistent_id, int options, int flags,
     965             :                 struct timeval *timeout,
     966             :                 php_stream_context *context STREAMS_DC TSRMLS_DC)
     967             : {
     968         985 :         php_stream *stream = NULL;
     969         985 :         php_openssl_netstream_data_t *sslsock = NULL;
     970             :         
     971         985 :         sslsock = pemalloc(sizeof(php_openssl_netstream_data_t), persistent_id ? 1 : 0);
     972         985 :         memset(sslsock, 0, sizeof(*sslsock));
     973             : 
     974         985 :         sslsock->s.is_blocked = 1;
     975             :         /* this timeout is used by standard stream funcs, therefor it should use the default value */
     976         985 :         sslsock->s.timeout.tv_sec = FG(default_socket_timeout);
     977         985 :         sslsock->s.timeout.tv_usec = 0;
     978             : 
     979             :         /* use separate timeout for our private funcs */
     980         985 :         sslsock->connect_timeout.tv_sec = timeout->tv_sec;
     981         985 :         sslsock->connect_timeout.tv_usec = timeout->tv_usec;
     982             : 
     983             :         /* we don't know the socket until we have determined if we are binding or
     984             :          * connecting */
     985         985 :         sslsock->s.socket = -1;
     986             :         
     987             :         /* Initialize context as NULL */
     988         985 :         sslsock->ctx = NULL; 
     989             :         
     990         985 :         stream = php_stream_alloc_rel(&php_openssl_socket_ops, sslsock, persistent_id, "r+");
     991             : 
     992         985 :         if (stream == NULL)     {
     993           0 :                 pefree(sslsock, persistent_id ? 1 : 0);
     994           0 :                 return NULL;
     995             :         }
     996             : 
     997         985 :         sslsock->sni = get_sni(context, resourcename, resourcenamelen, !!persistent_id TSRMLS_CC);
     998             :         
     999         985 :         if (strncmp(proto, "ssl", protolen) == 0) {
    1000          10 :                 sslsock->enable_on_connect = 1;
    1001          10 :                 sslsock->method = STREAM_CRYPTO_METHOD_SSLv23_CLIENT;
    1002         975 :         } else if (strncmp(proto, "sslv2", protolen) == 0) {
    1003             : #ifdef OPENSSL_NO_SSL2
    1004             :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSLv2 support is not compiled into the OpenSSL library PHP is linked against");
    1005             :                 return NULL;
    1006             : #else
    1007           0 :                 sslsock->enable_on_connect = 1;
    1008           0 :                 sslsock->method = STREAM_CRYPTO_METHOD_SSLv2_CLIENT;
    1009             : #endif
    1010         975 :         } else if (strncmp(proto, "sslv3", protolen) == 0) {
    1011           0 :                 sslsock->enable_on_connect = 1;
    1012           0 :                 sslsock->method = STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
    1013         975 :         } else if (strncmp(proto, "tls", protolen) == 0) {
    1014           0 :                 sslsock->enable_on_connect = 1;
    1015           0 :                 sslsock->method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
    1016             :         }
    1017             : 
    1018         985 :         return stream;
    1019             : }
    1020             : 
    1021             : 
    1022             : 
    1023             : /*
    1024             :  * Local variables:
    1025             :  * tab-width: 4
    1026             :  * c-basic-offset: 4
    1027             :  * End:
    1028             :  * vim600: noet sw=4 ts=4 fdm=marker
    1029             :  * vim<600: noet sw=4 ts=4
    1030             :  */

Generated by: LCOV version 1.10

Generated at Thu, 16 Oct 2014 05:27:06 +0000 (4 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.