This source file includes following definitions.
- is_http_stream_talking_to_iis
- handle_ssl_error
- verify_callback
- php_x509_fingerprint_cmp
- php_x509_fingerprint_match
- matches_wildcard_name
- matches_san_list
- matches_common_name
- apply_peer_verification_policy
- passwd_callback
- win_cert_verify_callback
- load_stream_cafile
- enable_peer_verification
- disable_peer_verification
- set_local_cert
- php_select_crypto_method
- php_get_crypto_method_ctx_flags
- limit_handshake_reneg
- info_callback
- init_server_reneg_limit
- tmp_rsa_cb
- set_server_dh_param
- set_server_ecdh_curve
- set_server_specific_opts
- server_sni_callback
- enable_server_sni
- enable_client_sni
- alpn_protos_parse
- server_alpn_callback
- php_openssl_setup_crypto
- capture_session_meta
- capture_peer_certs
- php_openssl_enable_crypto
- php_openssl_sockop_read
- php_openssl_sockop_write
- php_openssl_sockop_io
- subtract_timeval
- compare_timeval
- php_openssl_sockop_close
- php_openssl_sockop_flush
- php_openssl_sockop_stat
- php_openssl_tcp_sockop_accept
- php_openssl_sockop_set_option
- php_openssl_sockop_cast
- get_crypto_method
- get_url_name
- php_openssl_ssl_socket_factory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "php.h"
28 #include "ext/standard/file.h"
29 #include "ext/standard/url.h"
30 #include "streams/php_streams_int.h"
31 #include "zend_smart_str.h"
32 #include "php_openssl.h"
33 #include "php_network.h"
34 #include <openssl/ssl.h>
35 #include <openssl/rsa.h>
36 #include <openssl/x509.h>
37 #include <openssl/x509v3.h>
38 #include <openssl/err.h>
39
40 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
41 #include <openssl/bn.h>
42 #include <openssl/dh.h>
43 #endif
44
45 #ifdef PHP_WIN32
46 #include "win32/winutil.h"
47 #include "win32/time.h"
48 #include <Wincrypt.h>
49
50 #undef X509_NAME
51 #undef X509_CERT_PAIR
52 #undef X509_EXTENSIONS
53 #endif
54
55 #ifdef NETWARE
56 #include <sys/select.h>
57 #endif
58
59
60 #if OPENSSL_VERSION_NUMBER < 0x10002000L && !defined(OPENSSL_NO_SSL2)
61 #define HAVE_SSL2 1
62 #endif
63
64 #ifndef OPENSSL_NO_SSL3
65 #define HAVE_SSL3 1
66 #endif
67
68 #if OPENSSL_VERSION_NUMBER >= 0x10001001L
69 #define HAVE_TLS11 1
70 #define HAVE_TLS12 1
71 #endif
72
73 #if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x0090800fL
74 #define HAVE_ECDH 1
75 #endif
76
77 #if !defined(OPENSSL_NO_TLSEXT)
78 #if OPENSSL_VERSION_NUMBER >= 0x00908070L
79 #define HAVE_TLS_SNI 1
80 #endif
81 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
82 #define HAVE_TLS_ALPN 1
83 #endif
84 #endif
85
86
87
88 #define STREAM_CRYPTO_IS_CLIENT (1<<0)
89 #define STREAM_CRYPTO_METHOD_SSLv2 (1<<1)
90 #define STREAM_CRYPTO_METHOD_SSLv3 (1<<2)
91 #define STREAM_CRYPTO_METHOD_TLSv1_0 (1<<3)
92 #define STREAM_CRYPTO_METHOD_TLSv1_1 (1<<4)
93 #define STREAM_CRYPTO_METHOD_TLSv1_2 (1<<5)
94
95
96 #define GET_VER_OPT(name) (PHP_STREAM_CONTEXT(stream) && (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", name)) != NULL)
97 #define GET_VER_OPT_STRING(name, str) if (GET_VER_OPT(name)) { convert_to_string_ex(val); str = Z_STRVAL_P(val); }
98 #define GET_VER_OPT_LONG(name, num) if (GET_VER_OPT(name)) { convert_to_long_ex(val); num = Z_LVAL_P(val); }
99
100
101 #define PHP_X509_NAME_ENTRY_TO_UTF8(ne, i, out) ASN1_STRING_to_UTF8(&out, X509_NAME_ENTRY_get_data(X509_NAME_get_entry(ne, i)))
102
103 #ifndef OPENSSL_NO_RSA
104 static RSA *tmp_rsa_cb(SSL *s, int is_export, int keylength);
105 #endif
106
107 extern php_stream* php_openssl_get_stream_from_ssl_handle(const SSL *ssl);
108 extern zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, zend_bool raw);
109 extern int php_openssl_get_ssl_stream_data_index();
110 extern int php_openssl_get_x509_list_id(void);
111 static struct timeval subtract_timeval( struct timeval a, struct timeval b );
112 static int compare_timeval( struct timeval a, struct timeval b );
113 static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, size_t count);
114
115 php_stream_ops php_openssl_socket_ops;
116
117
118 typedef struct _php_openssl_sni_cert_t {
119 char *name;
120 SSL_CTX *ctx;
121 } php_openssl_sni_cert_t;
122
123
124 typedef struct _php_openssl_handshake_bucket_t {
125 zend_long prev_handshake;
126 zend_long limit;
127 zend_long window;
128 float tokens;
129 unsigned should_close;
130 } php_openssl_handshake_bucket_t;
131
132 #ifdef HAVE_TLS_ALPN
133
134 typedef struct _php_openssl_alpn_ctx_t {
135 unsigned char *data;
136 unsigned short len;
137 } php_openssl_alpn_ctx;
138 #endif
139
140
141
142
143
144 typedef struct _php_openssl_netstream_data_t {
145 php_netstream_data_t s;
146 SSL *ssl_handle;
147 SSL_CTX *ctx;
148 struct timeval connect_timeout;
149 int enable_on_connect;
150 int is_client;
151 int ssl_active;
152 php_stream_xport_crypt_method_t method;
153 php_openssl_handshake_bucket_t *reneg;
154 php_openssl_sni_cert_t *sni_certs;
155 unsigned sni_cert_count;
156 #ifdef HAVE_TLS_ALPN
157 php_openssl_alpn_ctx *alpn_ctx;
158 #endif
159 char *url_name;
160 unsigned state_set:1;
161 unsigned _spare:31;
162 } php_openssl_netstream_data_t;
163
164
165
166 static int is_http_stream_talking_to_iis(php_stream *stream)
167 {
168 if (Z_TYPE(stream->wrapperdata) == IS_ARRAY && stream->wrapper && strcasecmp(stream->wrapper->wops->label, "HTTP") == 0) {
169
170 zval *tmp;
171
172 #define SERVER_MICROSOFT_IIS "Server: Microsoft-IIS"
173 #define SERVER_GOOGLE "Server: GFE/"
174
175 ZEND_HASH_FOREACH_VAL(Z_ARRVAL(stream->wrapperdata), tmp) {
176 if (strncasecmp(Z_STRVAL_P(tmp), SERVER_MICROSOFT_IIS, sizeof(SERVER_MICROSOFT_IIS)-1) == 0) {
177 return 1;
178 } else if (strncasecmp(Z_STRVAL_P(tmp), SERVER_GOOGLE, sizeof(SERVER_GOOGLE)-1) == 0) {
179 return 1;
180 }
181 } ZEND_HASH_FOREACH_END();
182 }
183 return 0;
184 }
185
186
187 static int handle_ssl_error(php_stream *stream, int nr_bytes, zend_bool is_init)
188 {
189 php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
190 int err = SSL_get_error(sslsock->ssl_handle, nr_bytes);
191 char esbuf[512];
192 smart_str ebuf = {0};
193 unsigned long ecode;
194 int retry = 1;
195
196 switch(err) {
197 case SSL_ERROR_ZERO_RETURN:
198
199 retry = 0;
200 break;
201 case SSL_ERROR_WANT_READ:
202 case SSL_ERROR_WANT_WRITE:
203
204
205 errno = EAGAIN;
206 retry = is_init ? 1 : sslsock->s.is_blocked;
207 break;
208 case SSL_ERROR_SYSCALL:
209 if (ERR_peek_error() == 0) {
210 if (nr_bytes == 0) {
211 if (!is_http_stream_talking_to_iis(stream) && ERR_get_error() != 0) {
212 php_error_docref(NULL, E_WARNING,
213 "SSL: fatal protocol error");
214 }
215 SSL_set_shutdown(sslsock->ssl_handle, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
216 stream->eof = 1;
217 retry = 0;
218 } else {
219 char *estr = php_socket_strerror(php_socket_errno(), NULL, 0);
220
221 php_error_docref(NULL, E_WARNING,
222 "SSL: %s", estr);
223
224 efree(estr);
225 retry = 0;
226 }
227 break;
228 }
229
230
231
232 default:
233
234 ecode = ERR_get_error();
235
236 switch (ERR_GET_REASON(ecode)) {
237 case SSL_R_NO_SHARED_CIPHER:
238 php_error_docref(NULL, 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)");
239 retry = 0;
240 break;
241
242 default:
243 do {
244
245 ERR_error_string_n(ecode, esbuf, sizeof(esbuf));
246 if (ebuf.s) {
247 smart_str_appendc(&ebuf, '\n');
248 }
249 smart_str_appends(&ebuf, esbuf);
250 } while ((ecode = ERR_get_error()) != 0);
251
252 smart_str_0(&ebuf);
253
254 php_error_docref(NULL, E_WARNING,
255 "SSL operation failed with code %d. %s%s",
256 err,
257 ebuf.s ? "OpenSSL Error messages:\n" : "",
258 ebuf.s ? ZSTR_VAL(ebuf.s) : "");
259 if (ebuf.s) {
260 smart_str_free(&ebuf);
261 }
262 }
263
264 retry = 0;
265 errno = 0;
266 }
267 return retry;
268 }
269
270
271 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
272 {
273 php_stream *stream;
274 SSL *ssl;
275 int err, depth, ret;
276 zval *val;
277 zend_ulong allowed_depth = OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH;
278
279
280 ret = preverify_ok;
281
282
283 err = X509_STORE_CTX_get_error(ctx);
284 depth = X509_STORE_CTX_get_error_depth(ctx);
285
286
287 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
288 stream = (php_stream*)SSL_get_ex_data(ssl, php_openssl_get_ssl_stream_data_index());
289
290
291 if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT &&
292 GET_VER_OPT("allow_self_signed") &&
293 zend_is_true(val)
294 ) {
295 ret = 1;
296 }
297
298
299 GET_VER_OPT_LONG("verify_depth", allowed_depth);
300 if ((zend_ulong)depth > allowed_depth) {
301 ret = 0;
302 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_CHAIN_TOO_LONG);
303 }
304
305 return ret;
306 }
307
308
309 static int php_x509_fingerprint_cmp(X509 *peer, const char *method, const char *expected)
310 {
311 zend_string *fingerprint;
312 int result = -1;
313
314 fingerprint = php_openssl_x509_fingerprint(peer, method, 0);
315 if (fingerprint) {
316 result = strcasecmp(expected, ZSTR_VAL(fingerprint));
317 zend_string_release(fingerprint);
318 }
319
320 return result;
321 }
322
323 static zend_bool php_x509_fingerprint_match(X509 *peer, zval *val)
324 {
325 if (Z_TYPE_P(val) == IS_STRING) {
326 const char *method = NULL;
327
328 switch (Z_STRLEN_P(val)) {
329 case 32:
330 method = "md5";
331 break;
332
333 case 40:
334 method = "sha1";
335 break;
336 }
337
338 return method && php_x509_fingerprint_cmp(peer, method, Z_STRVAL_P(val)) == 0;
339 } else if (Z_TYPE_P(val) == IS_ARRAY) {
340 zval *current;
341 zend_string *key;
342
343 if (!zend_hash_num_elements(Z_ARRVAL_P(val))) {
344 php_error_docref(NULL, E_WARNING, "Invalid peer_fingerprint array; [algo => fingerprint] form required");
345 return 0;
346 }
347
348 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(val), key, current) {
349 if (key == NULL || Z_TYPE_P(current) != IS_STRING) {
350 php_error_docref(NULL, E_WARNING, "Invalid peer_fingerprint array; [algo => fingerprint] form required");
351 return 0;
352 }
353 if (php_x509_fingerprint_cmp(peer, ZSTR_VAL(key), Z_STRVAL_P(current)) != 0) {
354 return 0;
355 }
356 } ZEND_HASH_FOREACH_END();
357
358 return 1;
359 } else {
360 php_error_docref(NULL, E_WARNING,
361 "Invalid peer_fingerprint value; fingerprint string or array of the form [algo => fingerprint] required");
362 }
363
364 return 0;
365 }
366
367 static zend_bool matches_wildcard_name(const char *subjectname, const char *certname)
368 {
369 char *wildcard = NULL;
370 ptrdiff_t prefix_len;
371 size_t suffix_len, subject_len;
372
373 if (strcasecmp(subjectname, certname) == 0) {
374 return 1;
375 }
376
377
378 if (!(wildcard = strchr(certname, '*')) || memchr(certname, '.', wildcard - certname)) {
379 return 0;
380 }
381
382
383 prefix_len = wildcard - certname;
384 if (prefix_len && strncasecmp(subjectname, certname, prefix_len) != 0) {
385 return 0;
386 }
387
388 suffix_len = strlen(wildcard + 1);
389 subject_len = strlen(subjectname);
390 if (suffix_len <= subject_len) {
391
392
393
394 return strcasecmp(wildcard + 1, subjectname + subject_len - suffix_len) == 0 &&
395 memchr(subjectname + prefix_len, '.', subject_len - suffix_len - prefix_len) == NULL;
396 }
397
398 return 0;
399 }
400
401
402 static zend_bool matches_san_list(X509 *peer, const char *subject_name)
403 {
404 int i, len;
405 unsigned char *cert_name = NULL;
406 char ipbuffer[64];
407
408 GENERAL_NAMES *alt_names = X509_get_ext_d2i(peer, NID_subject_alt_name, 0, 0);
409 int alt_name_count = sk_GENERAL_NAME_num(alt_names);
410
411 for (i = 0; i < alt_name_count; i++) {
412 GENERAL_NAME *san = sk_GENERAL_NAME_value(alt_names, i);
413
414 if (san->type == GEN_DNS) {
415 ASN1_STRING_to_UTF8(&cert_name, san->d.dNSName);
416 if (ASN1_STRING_length(san->d.dNSName) != strlen((const char*)cert_name)) {
417 OPENSSL_free(cert_name);
418
419 continue;
420 }
421
422
423 len = strlen((const char*)cert_name);
424 if (len && strcmp((const char *)&cert_name[len-1], ".") == 0) {
425 cert_name[len-1] = '\0';
426 }
427
428 if (matches_wildcard_name(subject_name, (const char *)cert_name)) {
429 OPENSSL_free(cert_name);
430 return 1;
431 }
432 OPENSSL_free(cert_name);
433 } else if (san->type == GEN_IPADD) {
434 if (san->d.iPAddress->length == 4) {
435 sprintf(ipbuffer, "%d.%d.%d.%d",
436 san->d.iPAddress->data[0],
437 san->d.iPAddress->data[1],
438 san->d.iPAddress->data[2],
439 san->d.iPAddress->data[3]
440 );
441 if (strcasecmp(subject_name, (const char*)ipbuffer) == 0) {
442 return 1;
443 }
444 }
445
446
447
448
449 }
450 }
451
452 return 0;
453 }
454
455
456 static zend_bool matches_common_name(X509 *peer, const char *subject_name)
457 {
458 char buf[1024];
459 X509_NAME *cert_name;
460 zend_bool is_match = 0;
461 int cert_name_len;
462
463 cert_name = X509_get_subject_name(peer);
464 cert_name_len = X509_NAME_get_text_by_NID(cert_name, NID_commonName, buf, sizeof(buf));
465
466 if (cert_name_len == -1) {
467 php_error_docref(NULL, E_WARNING, "Unable to locate peer certificate CN");
468 } else if (cert_name_len != strlen(buf)) {
469 php_error_docref(NULL, E_WARNING, "Peer certificate CN=`%.*s' is malformed", cert_name_len, buf);
470 } else if (matches_wildcard_name(subject_name, buf)) {
471 is_match = 1;
472 } else {
473 php_error_docref(NULL, E_WARNING, "Peer certificate CN=`%.*s' did not match expected CN=`%s'", cert_name_len, buf, subject_name);
474 }
475
476 return is_match;
477 }
478
479
480 static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stream)
481 {
482 zval *val = NULL;
483 char *peer_name = NULL;
484 int err,
485 must_verify_peer,
486 must_verify_peer_name,
487 must_verify_fingerprint;
488
489 php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
490
491 must_verify_peer = GET_VER_OPT("verify_peer")
492 ? zend_is_true(val)
493 : sslsock->is_client;
494
495 must_verify_peer_name = GET_VER_OPT("verify_peer_name")
496 ? zend_is_true(val)
497 : sslsock->is_client;
498
499 must_verify_fingerprint = GET_VER_OPT("peer_fingerprint");
500
501 if ((must_verify_peer || must_verify_peer_name || must_verify_fingerprint) && peer == NULL) {
502 php_error_docref(NULL, E_WARNING, "Could not get peer certificate");
503 return FAILURE;
504 }
505
506
507 if (must_verify_peer) {
508 err = SSL_get_verify_result(ssl);
509 switch (err) {
510 case X509_V_OK:
511
512 break;
513 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
514 if (GET_VER_OPT("allow_self_signed") && zend_is_true(val)) {
515
516 break;
517 }
518
519 default:
520 php_error_docref(NULL, E_WARNING,
521 "Could not verify peer: code:%d %s",
522 err,
523 X509_verify_cert_error_string(err)
524 );
525 return FAILURE;
526 }
527 }
528
529
530 if (must_verify_fingerprint) {
531 if (Z_TYPE_P(val) == IS_STRING || Z_TYPE_P(val) == IS_ARRAY) {
532 if (!php_x509_fingerprint_match(peer, val)) {
533 php_error_docref(NULL, E_WARNING,
534 "peer_fingerprint match failure"
535 );
536 return FAILURE;
537 }
538 } else {
539 php_error_docref(NULL, E_WARNING,
540 "Expected peer fingerprint must be a string or an array"
541 );
542 return FAILURE;
543 }
544 }
545
546
547 if (must_verify_peer_name) {
548 GET_VER_OPT_STRING("peer_name", peer_name);
549
550
551 if (peer_name == NULL && sslsock->is_client) {
552 peer_name = sslsock->url_name;
553 }
554
555 if (peer_name) {
556 if (matches_san_list(peer, peer_name)) {
557 return SUCCESS;
558 } else if (matches_common_name(peer, peer_name)) {
559 return SUCCESS;
560 } else {
561 return FAILURE;
562 }
563 } else {
564 return FAILURE;
565 }
566 }
567
568 return SUCCESS;
569 }
570
571
572 static int passwd_callback(char *buf, int num, int verify, void *data)
573 {
574 php_stream *stream = (php_stream *)data;
575 zval *val = NULL;
576 char *passphrase = NULL;
577
578
579 GET_VER_OPT_STRING("passphrase", passphrase);
580
581 if (passphrase) {
582 if (Z_STRLEN_P(val) < num - 1) {
583 memcpy(buf, Z_STRVAL_P(val), Z_STRLEN_P(val)+1);
584 return (int)Z_STRLEN_P(val);
585 }
586 }
587 return 0;
588 }
589
590
591 #if defined(PHP_WIN32) && OPENSSL_VERSION_NUMBER >= 0x00907000L
592 #define RETURN_CERT_VERIFY_FAILURE(code) X509_STORE_CTX_set_error(x509_store_ctx, code); return 0;
593 static int win_cert_verify_callback(X509_STORE_CTX *x509_store_ctx, void *arg)
594 {
595 PCCERT_CONTEXT cert_ctx = NULL;
596 PCCERT_CHAIN_CONTEXT cert_chain_ctx = NULL;
597
598 php_stream *stream;
599 php_openssl_netstream_data_t *sslsock;
600 zval *val;
601 zend_bool is_self_signed = 0;
602
603
604 stream = (php_stream*)arg;
605 sslsock = (php_openssl_netstream_data_t*)stream->abstract;
606
607 {
608 unsigned char *der_buf = NULL;
609 int der_len;
610
611 der_len = i2d_X509(x509_store_ctx->cert, &der_buf);
612 if (der_len < 0) {
613 unsigned long err_code, e;
614 char err_buf[512];
615
616 while ((e = ERR_get_error()) != 0) {
617 err_code = e;
618 }
619
620 php_error_docref(NULL, E_WARNING, "Error encoding X509 certificate: %d: %s", err_code, ERR_error_string(err_code, err_buf));
621 RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
622 }
623
624 cert_ctx = CertCreateCertificateContext(X509_ASN_ENCODING, der_buf, der_len);
625 OPENSSL_free(der_buf);
626
627 if (cert_ctx == NULL) {
628 php_error_docref(NULL, E_WARNING, "Error creating certificate context: %s", php_win_err());
629 RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
630 }
631 }
632
633 {
634 CERT_ENHKEY_USAGE enhkey_usage = {0};
635 CERT_USAGE_MATCH cert_usage = {0};
636 CERT_CHAIN_PARA chain_params = {sizeof(CERT_CHAIN_PARA)};
637 LPSTR usages[] = {szOID_PKIX_KP_SERVER_AUTH, szOID_SERVER_GATED_CRYPTO, szOID_SGC_NETSCAPE};
638 DWORD chain_flags = 0;
639 unsigned long allowed_depth = OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH;
640 unsigned int i;
641
642 enhkey_usage.cUsageIdentifier = 3;
643 enhkey_usage.rgpszUsageIdentifier = usages;
644 cert_usage.dwType = USAGE_MATCH_TYPE_OR;
645 cert_usage.Usage = enhkey_usage;
646 chain_params.RequestedUsage = cert_usage;
647 chain_flags = CERT_CHAIN_CACHE_END_CERT | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
648
649 if (!CertGetCertificateChain(NULL, cert_ctx, NULL, NULL, &chain_params, chain_flags, NULL, &cert_chain_ctx)) {
650 php_error_docref(NULL, E_WARNING, "Error getting certificate chain: %s", php_win_err());
651 CertFreeCertificateContext(cert_ctx);
652 RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
653 }
654
655
656 if (cert_chain_ctx->cChain > 0 && cert_chain_ctx->rgpChain[0]->cElement > 0
657 && (cert_chain_ctx->rgpChain[0]->rgpElement[0]->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED) != 0) {
658 is_self_signed = 1;
659 }
660
661
662 GET_VER_OPT_LONG("verify_depth", allowed_depth);
663
664 for (i = 0; i < cert_chain_ctx->cChain; i++) {
665 if (cert_chain_ctx->rgpChain[i]->cElement > allowed_depth) {
666 CertFreeCertificateChain(cert_chain_ctx);
667 CertFreeCertificateContext(cert_ctx);
668 RETURN_CERT_VERIFY_FAILURE(X509_V_ERR_CERT_CHAIN_TOO_LONG);
669 }
670 }
671 }
672
673 {
674 SSL_EXTRA_CERT_CHAIN_POLICY_PARA ssl_policy_params = {sizeof(SSL_EXTRA_CERT_CHAIN_POLICY_PARA)};
675 CERT_CHAIN_POLICY_PARA chain_policy_params = {sizeof(CERT_CHAIN_POLICY_PARA)};
676 CERT_CHAIN_POLICY_STATUS chain_policy_status = {sizeof(CERT_CHAIN_POLICY_STATUS)};
677 LPWSTR server_name = NULL;
678 BOOL verify_result;
679
680 {
681
682
683 X509_NAME *cert_name;
684 unsigned char *cert_name_utf8;
685 int index, cert_name_utf8_len;
686 DWORD num_wchars;
687
688 cert_name = X509_get_subject_name(x509_store_ctx->cert);
689 index = X509_NAME_get_index_by_NID(cert_name, NID_commonName, -1);
690 if (index < 0) {
691 php_error_docref(NULL, E_WARNING, "Unable to locate certificate CN");
692 CertFreeCertificateChain(cert_chain_ctx);
693 CertFreeCertificateContext(cert_ctx);
694 RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
695 }
696
697 cert_name_utf8_len = PHP_X509_NAME_ENTRY_TO_UTF8(cert_name, index, cert_name_utf8);
698
699 num_wchars = MultiByteToWideChar(CP_UTF8, 0, (char*)cert_name_utf8, -1, NULL, 0);
700 if (num_wchars == 0) {
701 php_error_docref(NULL, E_WARNING, "Unable to convert %s to wide character string", cert_name_utf8);
702 OPENSSL_free(cert_name_utf8);
703 CertFreeCertificateChain(cert_chain_ctx);
704 CertFreeCertificateContext(cert_ctx);
705 RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
706 }
707
708 server_name = emalloc((num_wchars * sizeof(WCHAR)) + sizeof(WCHAR));
709
710 num_wchars = MultiByteToWideChar(CP_UTF8, 0, (char*)cert_name_utf8, -1, server_name, num_wchars);
711 if (num_wchars == 0) {
712 php_error_docref(NULL, E_WARNING, "Unable to convert %s to wide character string", cert_name_utf8);
713 efree(server_name);
714 OPENSSL_free(cert_name_utf8);
715 CertFreeCertificateChain(cert_chain_ctx);
716 CertFreeCertificateContext(cert_ctx);
717 RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
718 }
719
720 OPENSSL_free(cert_name_utf8);
721 }
722
723 ssl_policy_params.dwAuthType = (sslsock->is_client) ? AUTHTYPE_SERVER : AUTHTYPE_CLIENT;
724 ssl_policy_params.pwszServerName = server_name;
725 chain_policy_params.pvExtraPolicyPara = &ssl_policy_params;
726
727 verify_result = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, cert_chain_ctx, &chain_policy_params, &chain_policy_status);
728
729 efree(server_name);
730 CertFreeCertificateChain(cert_chain_ctx);
731 CertFreeCertificateContext(cert_ctx);
732
733 if (!verify_result) {
734 php_error_docref(NULL, E_WARNING, "Error verifying certificate chain policy: %s", php_win_err());
735 RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
736 }
737
738 if (chain_policy_status.dwError != 0) {
739
740 if (is_self_signed && chain_policy_status.dwError == CERT_E_UNTRUSTEDROOT
741 && GET_VER_OPT("allow_self_signed") && zend_is_true(val)) {
742
743 X509_STORE_CTX_set_error(x509_store_ctx, X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT);
744 } else {
745 RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
746 }
747 }
748 }
749
750 return 1;
751 }
752
753 #endif
754
755 static long load_stream_cafile(X509_STORE *cert_store, const char *cafile)
756 {
757 php_stream *stream;
758 X509 *cert;
759 BIO *buffer;
760 int buffer_active = 0;
761 char *line = NULL;
762 size_t line_len;
763 long certs_added = 0;
764
765 stream = php_stream_open_wrapper(cafile, "rb", 0, NULL);
766
767 if (stream == NULL) {
768 php_error(E_WARNING, "failed loading cafile stream: `%s'", cafile);
769 return 0;
770 } else if (stream->wrapper->is_url) {
771 php_stream_close(stream);
772 php_error(E_WARNING, "remote cafile streams are disabled for security purposes");
773 return 0;
774 }
775
776 cert_start: {
777 line = php_stream_get_line(stream, NULL, 0, &line_len);
778 if (line == NULL) {
779 goto stream_complete;
780 } else if (!strcmp(line, "-----BEGIN CERTIFICATE-----\n") ||
781 !strcmp(line, "-----BEGIN CERTIFICATE-----\r\n")
782 ) {
783 buffer = BIO_new(BIO_s_mem());
784 buffer_active = 1;
785 goto cert_line;
786 } else {
787 efree(line);
788 goto cert_start;
789 }
790 }
791
792 cert_line: {
793 BIO_puts(buffer, line);
794 efree(line);
795 line = php_stream_get_line(stream, NULL, 0, &line_len);
796 if (line == NULL) {
797 goto stream_complete;
798 } else if (!strcmp(line, "-----END CERTIFICATE-----") ||
799 !strcmp(line, "-----END CERTIFICATE-----\n") ||
800 !strcmp(line, "-----END CERTIFICATE-----\r\n")
801 ) {
802 goto add_cert;
803 } else {
804 goto cert_line;
805 }
806 }
807
808 add_cert: {
809 BIO_puts(buffer, line);
810 efree(line);
811 cert = PEM_read_bio_X509(buffer, NULL, 0, NULL);
812 BIO_free(buffer);
813 buffer_active = 0;
814 if (cert && X509_STORE_add_cert(cert_store, cert)) {
815 ++certs_added;
816 }
817 goto cert_start;
818 }
819
820 stream_complete: {
821 php_stream_close(stream);
822 if (buffer_active == 1) {
823 BIO_free(buffer);
824 }
825 }
826
827 if (certs_added == 0) {
828 php_error(E_WARNING, "no valid certs found cafile stream: `%s'", cafile);
829 }
830
831 return certs_added;
832 }
833
834
835 static int enable_peer_verification(SSL_CTX *ctx, php_stream *stream)
836 {
837 zval *val = NULL;
838 char *cafile = NULL;
839 char *capath = NULL;
840 php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
841
842 GET_VER_OPT_STRING("cafile", cafile);
843 GET_VER_OPT_STRING("capath", capath);
844
845 if (cafile == NULL) {
846 cafile = zend_ini_string("openssl.cafile", sizeof("openssl.cafile")-1, 0);
847 cafile = strlen(cafile) ? cafile : NULL;
848 } else if (!sslsock->is_client) {
849
850 STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(cafile);
851 if (cert_names != NULL) {
852 SSL_CTX_set_client_CA_list(ctx, cert_names);
853 } else {
854 php_error(E_WARNING, "SSL: failed loading CA names from cafile");
855 return FAILURE;
856 }
857 }
858
859 if (capath == NULL) {
860 capath = zend_ini_string("openssl.capath", sizeof("openssl.capath")-1, 0);
861 capath = strlen(capath) ? capath : NULL;
862 }
863
864 if (cafile || capath) {
865 if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) {
866 if (cafile && !load_stream_cafile(SSL_CTX_get_cert_store(ctx), cafile)) {
867 return FAILURE;
868 }
869 }
870 } else {
871 #if defined(PHP_WIN32) && OPENSSL_VERSION_NUMBER >= 0x00907000L
872 SSL_CTX_set_cert_verify_callback(ctx, win_cert_verify_callback, (void *)stream);
873 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
874 #else
875 if (sslsock->is_client && !SSL_CTX_set_default_verify_paths(ctx)) {
876 php_error_docref(NULL, E_WARNING,
877 "Unable to set default verify locations and no CA settings specified");
878 return FAILURE;
879 }
880 #endif
881 }
882
883 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
884
885 return SUCCESS;
886 }
887
888
889 static void disable_peer_verification(SSL_CTX *ctx, php_stream *stream)
890 {
891 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
892 }
893
894
895 static int set_local_cert(SSL_CTX *ctx, php_stream *stream)
896 {
897 zval *val = NULL;
898 char *certfile = NULL;
899
900 GET_VER_OPT_STRING("local_cert", certfile);
901
902 if (certfile) {
903 char resolved_path_buff[MAXPATHLEN];
904 const char * private_key = NULL;
905
906 if (VCWD_REALPATH(certfile, resolved_path_buff)) {
907
908 if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) {
909 php_error_docref(NULL, E_WARNING, "Unable to set local cert chain file `%s'; Check that your cafile/capath settings include details of your certificate and its issuer", certfile);
910 return FAILURE;
911 }
912 GET_VER_OPT_STRING("local_pk", private_key);
913
914 if (private_key) {
915 char resolved_path_buff_pk[MAXPATHLEN];
916 if (VCWD_REALPATH(private_key, resolved_path_buff_pk)) {
917 if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff_pk, SSL_FILETYPE_PEM) != 1) {
918 php_error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff_pk);
919 return FAILURE;
920 }
921 }
922 } else {
923 if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) {
924 php_error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff);
925 return FAILURE;
926 }
927 }
928
929 #if OPENSSL_VERSION_NUMBER < 0x10001001L
930 do {
931
932 X509 *cert = NULL;
933 EVP_PKEY *key = NULL;
934 SSL *tmpssl = SSL_new(ctx);
935 cert = SSL_get_certificate(tmpssl);
936
937 if (cert) {
938 key = X509_get_pubkey(cert);
939 EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl));
940 EVP_PKEY_free(key);
941 }
942 SSL_free(tmpssl);
943 } while (0);
944 #endif
945 if (!SSL_CTX_check_private_key(ctx)) {
946 php_error_docref(NULL, E_WARNING, "Private key does not match certificate!");
947 }
948 }
949 }
950
951 return SUCCESS;
952 }
953
954
955 static const SSL_METHOD *php_select_crypto_method(zend_long method_value, int is_client)
956 {
957 if (method_value == STREAM_CRYPTO_METHOD_SSLv2) {
958 #ifdef HAVE_SSL2
959 return is_client ? (SSL_METHOD *)SSLv2_client_method() : (SSL_METHOD *)SSLv2_server_method();
960 #else
961 php_error_docref(NULL, E_WARNING,
962 "SSLv2 unavailable in the OpenSSL library against which PHP is linked");
963 return NULL;
964 #endif
965 } else if (method_value == STREAM_CRYPTO_METHOD_SSLv3) {
966 #ifdef HAVE_SSL3
967 return is_client ? SSLv3_client_method() : SSLv3_server_method();
968 #else
969 php_error_docref(NULL, E_WARNING,
970 "SSLv3 unavailable in the OpenSSL library against which PHP is linked");
971 return NULL;
972 #endif
973 } else if (method_value == STREAM_CRYPTO_METHOD_TLSv1_0) {
974 return is_client ? TLSv1_client_method() : TLSv1_server_method();
975 } else if (method_value == STREAM_CRYPTO_METHOD_TLSv1_1) {
976 #ifdef HAVE_TLS11
977 return is_client ? TLSv1_1_client_method() : TLSv1_1_server_method();
978 #else
979 php_error_docref(NULL, E_WARNING,
980 "TLSv1.1 unavailable in the OpenSSL library against which PHP is linked");
981 return NULL;
982 #endif
983 } else if (method_value == STREAM_CRYPTO_METHOD_TLSv1_2) {
984 #ifdef HAVE_TLS12
985 return is_client ? TLSv1_2_client_method() : TLSv1_2_server_method();
986 #else
987 php_error_docref(NULL, E_WARNING,
988 "TLSv1.2 unavailable in the OpenSSL library against which PHP is linked");
989 return NULL;
990 #endif
991 } else {
992 php_error_docref(NULL, E_WARNING,
993 "Invalid crypto method");
994 return NULL;
995 }
996 }
997
998
999 static int php_get_crypto_method_ctx_flags(int method_flags)
1000 {
1001 int ssl_ctx_options = SSL_OP_ALL;
1002
1003 #ifdef HAVE_SSL2
1004 if (!(method_flags & STREAM_CRYPTO_METHOD_SSLv2)) {
1005 ssl_ctx_options |= SSL_OP_NO_SSLv2;
1006 }
1007 #endif
1008 #ifdef HAVE_SSL3
1009 if (!(method_flags & STREAM_CRYPTO_METHOD_SSLv3)) {
1010 ssl_ctx_options |= SSL_OP_NO_SSLv3;
1011 }
1012 #endif
1013 if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_0)) {
1014 ssl_ctx_options |= SSL_OP_NO_TLSv1;
1015 }
1016 #ifdef HAVE_TLS11
1017 if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_1)) {
1018 ssl_ctx_options |= SSL_OP_NO_TLSv1_1;
1019 }
1020 #endif
1021 #ifdef HAVE_TLS12
1022 if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_2)) {
1023 ssl_ctx_options |= SSL_OP_NO_TLSv1_2;
1024 }
1025 #endif
1026
1027 return ssl_ctx_options;
1028 }
1029
1030
1031 static void limit_handshake_reneg(const SSL *ssl)
1032 {
1033 php_stream *stream;
1034 php_openssl_netstream_data_t *sslsock;
1035 struct timeval now;
1036 zend_long elapsed_time;
1037
1038 stream = php_openssl_get_stream_from_ssl_handle(ssl);
1039 sslsock = (php_openssl_netstream_data_t*)stream->abstract;
1040 gettimeofday(&now, NULL);
1041
1042
1043 if (sslsock->reneg->prev_handshake == 0) {
1044 sslsock->reneg->prev_handshake = now.tv_sec;
1045 return;
1046 }
1047
1048 elapsed_time = (now.tv_sec - sslsock->reneg->prev_handshake);
1049 sslsock->reneg->prev_handshake = now.tv_sec;
1050 sslsock->reneg->tokens -= (elapsed_time * (sslsock->reneg->limit / sslsock->reneg->window));
1051
1052 if (sslsock->reneg->tokens < 0) {
1053 sslsock->reneg->tokens = 0;
1054 }
1055 ++sslsock->reneg->tokens;
1056
1057
1058 if (sslsock->reneg->tokens > sslsock->reneg->limit) {
1059 zval *val;
1060
1061
1062 sslsock->reneg->should_close = 1;
1063
1064 if (PHP_STREAM_CONTEXT(stream) && (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream),
1065 "ssl", "reneg_limit_callback")) != NULL
1066 ) {
1067 zval param, retval;
1068
1069 php_stream_to_zval(stream, ¶m);
1070
1071
1072 stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE;
1073 if (FAILURE == call_user_function_ex(EG(function_table), NULL, val, &retval, 1, ¶m, 0, NULL)) {
1074 php_error(E_WARNING, "SSL: failed invoking reneg limit notification callback");
1075 }
1076 stream->flags ^= PHP_STREAM_FLAG_NO_FCLOSE;
1077
1078
1079 if (Z_TYPE(retval) == IS_TRUE) {
1080 sslsock->reneg->should_close = 0;
1081 }
1082
1083 zval_ptr_dtor(&retval);
1084 } else {
1085 php_error_docref(NULL, E_WARNING,
1086 "SSL: client-initiated handshake rate limit exceeded by peer");
1087 }
1088 }
1089 }
1090
1091
1092 static void info_callback(const SSL *ssl, int where, int ret)
1093 {
1094
1095 if (where & SSL_CB_HANDSHAKE_START) {
1096 limit_handshake_reneg(ssl);
1097 }
1098 }
1099
1100
1101 static void init_server_reneg_limit(php_stream *stream, php_openssl_netstream_data_t *sslsock)
1102 {
1103 zval *val;
1104 zend_long limit = OPENSSL_DEFAULT_RENEG_LIMIT;
1105 zend_long window = OPENSSL_DEFAULT_RENEG_WINDOW;
1106
1107 if (PHP_STREAM_CONTEXT(stream) &&
1108 NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream),
1109 "ssl", "reneg_limit"))
1110 ) {
1111 convert_to_long(val);
1112 limit = Z_LVAL_P(val);
1113 }
1114
1115
1116 if (limit < 0) {
1117 return;
1118 }
1119
1120 if (PHP_STREAM_CONTEXT(stream) &&
1121 NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream),
1122 "ssl", "reneg_window"))
1123 ) {
1124 convert_to_long(val);
1125 window = Z_LVAL_P(val);
1126 }
1127
1128 sslsock->reneg = (void*)pemalloc(sizeof(php_openssl_handshake_bucket_t),
1129 php_stream_is_persistent(stream)
1130 );
1131
1132 sslsock->reneg->limit = limit;
1133 sslsock->reneg->window = window;
1134 sslsock->reneg->prev_handshake = 0;
1135 sslsock->reneg->tokens = 0;
1136 sslsock->reneg->should_close = 0;
1137
1138 SSL_set_info_callback(sslsock->ssl_handle, info_callback);
1139 }
1140
1141
1142 #ifndef OPENSSL_NO_RSA
1143 static RSA *tmp_rsa_cb(SSL *s, int is_export, int keylength)
1144 {
1145 BIGNUM *bn = NULL;
1146 static RSA *rsa_tmp = NULL;
1147
1148 if (!rsa_tmp && ((bn = BN_new()) == NULL)) {
1149 php_error_docref(NULL, E_WARNING, "allocation error generating RSA key");
1150 }
1151 if (!rsa_tmp && bn) {
1152 if (!BN_set_word(bn, RSA_F4) || ((rsa_tmp = RSA_new()) == NULL) ||
1153 !RSA_generate_key_ex(rsa_tmp, keylength, bn, NULL)) {
1154 if (rsa_tmp) {
1155 RSA_free(rsa_tmp);
1156 }
1157 rsa_tmp = NULL;
1158 }
1159 BN_free(bn);
1160 }
1161
1162 return (rsa_tmp);
1163 }
1164 #endif
1165
1166 #ifndef OPENSSL_NO_DH
1167 static int set_server_dh_param(php_stream * stream, SSL_CTX *ctx)
1168 {
1169 DH *dh;
1170 BIO* bio;
1171 zval *zdhpath;
1172
1173 zdhpath = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "dh_param");
1174 if (zdhpath == NULL) {
1175 #if 0
1176
1177
1178
1179 SSL_CTX_set_dh_auto(ctx, 1);
1180 #endif
1181 return SUCCESS;
1182 }
1183
1184 convert_to_string_ex(zdhpath);
1185 bio = BIO_new_file(Z_STRVAL_P(zdhpath), "r");
1186
1187 if (bio == NULL) {
1188 php_error_docref(NULL, E_WARNING, "invalid dh_param");
1189 return FAILURE;
1190 }
1191
1192 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
1193 BIO_free(bio);
1194
1195 if (dh == NULL) {
1196 php_error_docref(NULL, E_WARNING, "failed reading DH params");
1197 return FAILURE;
1198 }
1199
1200 if (SSL_CTX_set_tmp_dh(ctx, dh) < 0) {
1201 php_error_docref(NULL, E_WARNING, "failed assigning DH params");
1202 DH_free(dh);
1203 return FAILURE;
1204 }
1205
1206 DH_free(dh);
1207
1208 return SUCCESS;
1209 }
1210
1211 #endif
1212
1213 #ifdef HAVE_ECDH
1214 static int set_server_ecdh_curve(php_stream *stream, SSL_CTX *ctx)
1215 {
1216 zval *zvcurve;
1217 int curve_nid;
1218 EC_KEY *ecdh;
1219
1220 zvcurve = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "ecdh_curve");
1221 if (zvcurve == NULL) {
1222 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
1223 SSL_CTX_set_ecdh_auto(ctx, 1);
1224 return SUCCESS;
1225 #else
1226 curve_nid = NID_X9_62_prime256v1;
1227 #endif
1228 } else {
1229 convert_to_string_ex(zvcurve);
1230 curve_nid = OBJ_sn2nid(Z_STRVAL_P(zvcurve));
1231 if (curve_nid == NID_undef) {
1232 php_error_docref(NULL, E_WARNING, "invalid ecdh_curve specified");
1233 return FAILURE;
1234 }
1235 }
1236
1237 ecdh = EC_KEY_new_by_curve_name(curve_nid);
1238 if (ecdh == NULL) {
1239 php_error_docref(NULL, E_WARNING, "failed generating ECDH curve");
1240 return FAILURE;
1241 }
1242
1243 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
1244 EC_KEY_free(ecdh);
1245
1246 return SUCCESS;
1247 }
1248
1249 #endif
1250
1251 static int set_server_specific_opts(php_stream *stream, SSL_CTX *ctx)
1252 {
1253 zval *zv;
1254 long ssl_ctx_options = SSL_CTX_get_options(ctx);
1255
1256 #ifdef HAVE_ECDH
1257 if (set_server_ecdh_curve(stream, ctx) == FAILURE) {
1258 return FAILURE;
1259 }
1260 #endif
1261
1262 #ifndef OPENSSL_NO_RSA
1263 SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb);
1264 #endif
1265
1266 if (php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "rsa_key_size") != NULL) {
1267 php_error_docref(NULL, E_WARNING, "rsa_key_size context option has been removed");
1268 }
1269
1270 #ifndef OPENSSL_NO_DH
1271 set_server_dh_param(stream, ctx);
1272 zv = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "single_dh_use");
1273 if (zv != NULL && zend_is_true(zv)) {
1274 ssl_ctx_options |= SSL_OP_SINGLE_DH_USE;
1275 }
1276 #endif
1277
1278 zv = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "honor_cipher_order");
1279 if (zv != NULL && zend_is_true(zv)) {
1280 ssl_ctx_options |= SSL_OP_CIPHER_SERVER_PREFERENCE;
1281 }
1282
1283 SSL_CTX_set_options(ctx, ssl_ctx_options);
1284
1285 return SUCCESS;
1286 }
1287
1288
1289 #ifdef HAVE_TLS_SNI
1290 static int server_sni_callback(SSL *ssl_handle, int *al, void *arg)
1291 {
1292 php_stream *stream;
1293 php_openssl_netstream_data_t *sslsock;
1294 unsigned i;
1295 const char *server_name;
1296
1297 server_name = SSL_get_servername(ssl_handle, TLSEXT_NAMETYPE_host_name);
1298
1299 if (!server_name) {
1300 return SSL_TLSEXT_ERR_NOACK;
1301 }
1302
1303 stream = (php_stream*)SSL_get_ex_data(ssl_handle, php_openssl_get_ssl_stream_data_index());
1304 sslsock = (php_openssl_netstream_data_t*)stream->abstract;
1305
1306 if (!(sslsock->sni_cert_count && sslsock->sni_certs)) {
1307 return SSL_TLSEXT_ERR_NOACK;
1308 }
1309
1310 for (i=0; i < sslsock->sni_cert_count; i++) {
1311 if (matches_wildcard_name(server_name, sslsock->sni_certs[i].name)) {
1312 SSL_set_SSL_CTX(ssl_handle, sslsock->sni_certs[i].ctx);
1313 return SSL_TLSEXT_ERR_OK;
1314 }
1315 }
1316
1317 return SSL_TLSEXT_ERR_NOACK;
1318 }
1319
1320
1321 static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock)
1322 {
1323 zval *val;
1324 zval *current;
1325 zend_string *key;
1326 zend_ulong key_index;
1327 int i = 0;
1328 char resolved_path_buff[MAXPATHLEN];
1329 SSL_CTX *ctx;
1330
1331
1332 if (GET_VER_OPT("SNI_enabled") && !zend_is_true(val)) {
1333 return SUCCESS;
1334 }
1335
1336
1337 if (!GET_VER_OPT("SNI_server_certs")) {
1338 return SUCCESS;
1339 }
1340
1341 if (Z_TYPE_P(val) != IS_ARRAY) {
1342 php_error_docref(NULL, E_WARNING,
1343 "SNI_server_certs requires an array mapping host names to cert paths"
1344 );
1345 return FAILURE;
1346 }
1347
1348 sslsock->sni_cert_count = zend_hash_num_elements(Z_ARRVAL_P(val));
1349 if (sslsock->sni_cert_count == 0) {
1350 php_error_docref(NULL, E_WARNING,
1351 "SNI_server_certs host cert array must not be empty"
1352 );
1353 return FAILURE;
1354 }
1355
1356 sslsock->sni_certs = (php_openssl_sni_cert_t*)safe_pemalloc(sslsock->sni_cert_count,
1357 sizeof(php_openssl_sni_cert_t), 0, php_stream_is_persistent(stream)
1358 );
1359
1360 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(val), key_index, key, current) {
1361 (void) key_index;
1362
1363 if (!key) {
1364 php_error_docref(NULL, E_WARNING,
1365 "SNI_server_certs array requires string host name keys"
1366 );
1367 return FAILURE;
1368 }
1369
1370 if (VCWD_REALPATH(Z_STRVAL_P(current), resolved_path_buff)) {
1371
1372
1373 ctx = SSL_CTX_new(SSLv23_server_method());
1374
1375 if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) {
1376 php_error_docref(NULL, E_WARNING,
1377 "failed setting local cert chain file `%s'; " \
1378 "check that your cafile/capath settings include " \
1379 "details of your certificate and its issuer",
1380 resolved_path_buff
1381 );
1382 SSL_CTX_free(ctx);
1383 return FAILURE;
1384 } else if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) {
1385 php_error_docref(NULL, E_WARNING,
1386 "failed setting private key from file `%s'",
1387 resolved_path_buff
1388 );
1389 SSL_CTX_free(ctx);
1390 return FAILURE;
1391 } else {
1392 sslsock->sni_certs[i].name = pestrdup(ZSTR_VAL(key), php_stream_is_persistent(stream));
1393 sslsock->sni_certs[i].ctx = ctx;
1394 ++i;
1395 }
1396 } else {
1397 php_error_docref(NULL, E_WARNING,
1398 "failed setting local cert chain file `%s'; file not found",
1399 Z_STRVAL_P(current)
1400 );
1401 return FAILURE;
1402 }
1403 } ZEND_HASH_FOREACH_END();
1404
1405 SSL_CTX_set_tlsext_servername_callback(sslsock->ctx, server_sni_callback);
1406
1407 return SUCCESS;
1408 }
1409
1410 static void enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock)
1411 {
1412 zval *val;
1413 char *sni_server_name;
1414
1415
1416 if (GET_VER_OPT("SNI_enabled") && !zend_is_true(val)) {
1417 return;
1418 }
1419
1420 sni_server_name = sslsock->url_name;
1421
1422 GET_VER_OPT_STRING("peer_name", sni_server_name);
1423
1424 if (sni_server_name) {
1425 SSL_set_tlsext_host_name(sslsock->ssl_handle, sni_server_name);
1426 }
1427 }
1428
1429 #endif
1430
1431 #ifdef HAVE_TLS_ALPN
1432
1433
1434
1435
1436
1437
1438
1439
1440 static unsigned char *alpn_protos_parse(unsigned short *outlen, const char *in)
1441 {
1442 size_t len;
1443 unsigned char *out;
1444 size_t i, start = 0;
1445
1446 len = strlen(in);
1447 if (len >= 65535) {
1448 return NULL;
1449 }
1450
1451 out = emalloc(strlen(in) + 1);
1452 if (!out) {
1453 return NULL;
1454 }
1455
1456 for (i = 0; i <= len; ++i) {
1457 if (i == len || in[i] == ',') {
1458 if (i - start > 255) {
1459 efree(out);
1460 return NULL;
1461 }
1462 out[start] = i - start;
1463 start = i + 1;
1464 } else {
1465 out[i + 1] = in[i];
1466 }
1467 }
1468
1469 *outlen = len + 1;
1470
1471 return out;
1472 }
1473
1474 static int server_alpn_callback(SSL *ssl_handle, const unsigned char **out, unsigned char *outlen,
1475 const unsigned char *in, unsigned int inlen, void *arg)
1476 {
1477 php_openssl_netstream_data_t *sslsock = arg;
1478
1479 if (SSL_select_next_proto
1480 ((unsigned char **)out, outlen, sslsock->alpn_ctx->data, sslsock->alpn_ctx->len, in,
1481 inlen) != OPENSSL_NPN_NEGOTIATED) {
1482 return SSL_TLSEXT_ERR_NOACK;
1483 }
1484
1485 return SSL_TLSEXT_ERR_OK;
1486 }
1487
1488 #endif
1489
1490 int php_openssl_setup_crypto(php_stream *stream,
1491 php_openssl_netstream_data_t *sslsock,
1492 php_stream_xport_crypto_param *cparam
1493 )
1494 {
1495 const SSL_METHOD *method;
1496 int ssl_ctx_options;
1497 int method_flags;
1498 char *cipherlist = NULL;
1499 char *alpn_protocols = NULL;
1500 zval *val;
1501
1502 if (sslsock->ssl_handle) {
1503 if (sslsock->s.is_blocked) {
1504 php_error_docref(NULL, E_WARNING, "SSL/TLS already set-up for this stream");
1505 return FAILURE;
1506 } else {
1507 return SUCCESS;
1508 }
1509 }
1510
1511 ERR_clear_error();
1512
1513
1514
1515 sslsock->is_client = cparam->inputs.method & STREAM_CRYPTO_IS_CLIENT;
1516 method_flags = ((cparam->inputs.method >> 1) << 1);
1517
1518
1519 if ((method_flags & (method_flags-1)) == 0) {
1520 ssl_ctx_options = SSL_OP_ALL;
1521 method = php_select_crypto_method(method_flags, sslsock->is_client);
1522 if (method == NULL) {
1523 return FAILURE;
1524 }
1525 } else {
1526 method = sslsock->is_client ? SSLv23_client_method() : SSLv23_server_method();
1527 ssl_ctx_options = php_get_crypto_method_ctx_flags(method_flags);
1528 if (ssl_ctx_options == -1) {
1529 return FAILURE;
1530 }
1531 }
1532
1533 #if OPENSSL_VERSION_NUMBER >= 0x10001001L
1534 sslsock->ctx = SSL_CTX_new(method);
1535 #else
1536
1537 sslsock->ctx = SSL_CTX_new((SSL_METHOD*)method);
1538 #endif
1539
1540 if (sslsock->ctx == NULL) {
1541 php_error_docref(NULL, E_WARNING, "SSL context creation failure");
1542 return FAILURE;
1543 }
1544
1545 #if OPENSSL_VERSION_NUMBER >= 0x0090806fL
1546 if (GET_VER_OPT("no_ticket") && zend_is_true(val)) {
1547 ssl_ctx_options |= SSL_OP_NO_TICKET;
1548 }
1549 #endif
1550
1551 #if OPENSSL_VERSION_NUMBER >= 0x0090605fL
1552 ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
1553 #endif
1554
1555 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1556 if (!GET_VER_OPT("disable_compression") || zend_is_true(val)) {
1557 ssl_ctx_options |= SSL_OP_NO_COMPRESSION;
1558 }
1559 #endif
1560
1561 if (GET_VER_OPT("verify_peer") && !zend_is_true(val)) {
1562 disable_peer_verification(sslsock->ctx, stream);
1563 } else if (FAILURE == enable_peer_verification(sslsock->ctx, stream)) {
1564 return FAILURE;
1565 }
1566
1567
1568 if (GET_VER_OPT("passphrase")) {
1569 SSL_CTX_set_default_passwd_cb_userdata(sslsock->ctx, stream);
1570 SSL_CTX_set_default_passwd_cb(sslsock->ctx, passwd_callback);
1571 }
1572
1573 GET_VER_OPT_STRING("ciphers", cipherlist);
1574 #ifndef USE_OPENSSL_SYSTEM_CIPHERS
1575 if (!cipherlist) {
1576 cipherlist = OPENSSL_DEFAULT_STREAM_CIPHERS;
1577 }
1578 #endif
1579 if (cipherlist) {
1580 if (SSL_CTX_set_cipher_list(sslsock->ctx, cipherlist) != 1) {
1581 return FAILURE;
1582 }
1583 }
1584
1585 GET_VER_OPT_STRING("alpn_protocols", alpn_protocols);
1586 if (alpn_protocols) {
1587 #ifdef HAVE_TLS_ALPN
1588 {
1589 unsigned short alpn_len;
1590 unsigned char *alpn = alpn_protos_parse(&alpn_len, alpn_protocols);
1591
1592 if (alpn == NULL) {
1593 php_error_docref(NULL, E_WARNING, "Failed parsing comma-separated TLS ALPN protocol string");
1594 SSL_CTX_free(sslsock->ctx);
1595 sslsock->ctx = NULL;
1596 return FAILURE;
1597 }
1598 if (sslsock->is_client) {
1599 SSL_CTX_set_alpn_protos(sslsock->ctx, alpn, alpn_len);
1600 } else {
1601 sslsock->alpn_ctx = (php_openssl_alpn_ctx *) emalloc(sizeof(php_openssl_alpn_ctx));
1602 sslsock->alpn_ctx->data = (unsigned char*)estrndup((const char*)alpn, alpn_len);
1603 sslsock->alpn_ctx->len = alpn_len;
1604 SSL_CTX_set_alpn_select_cb(sslsock->ctx, server_alpn_callback, sslsock);
1605 }
1606
1607 efree(alpn);
1608 }
1609 #else
1610 php_error_docref(NULL, E_WARNING,
1611 "alpn_protocols support is not compiled into the OpenSSL library against which PHP is linked");
1612 #endif
1613 }
1614
1615 if (FAILURE == set_local_cert(sslsock->ctx, stream)) {
1616 return FAILURE;
1617 }
1618
1619 SSL_CTX_set_options(sslsock->ctx, ssl_ctx_options);
1620
1621 if (sslsock->is_client == 0 &&
1622 PHP_STREAM_CONTEXT(stream) &&
1623 FAILURE == set_server_specific_opts(stream, sslsock->ctx)
1624 ) {
1625 return FAILURE;
1626 }
1627
1628 sslsock->ssl_handle = SSL_new(sslsock->ctx);
1629
1630 if (sslsock->ssl_handle == NULL) {
1631 php_error_docref(NULL, E_WARNING, "SSL handle creation failure");
1632 SSL_CTX_free(sslsock->ctx);
1633 sslsock->ctx = NULL;
1634 return FAILURE;
1635 } else {
1636 SSL_set_ex_data(sslsock->ssl_handle, php_openssl_get_ssl_stream_data_index(), stream);
1637 }
1638
1639 if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) {
1640 handle_ssl_error(stream, 0, 1);
1641 }
1642
1643 #ifdef HAVE_TLS_SNI
1644
1645 if (!sslsock->is_client && enable_server_sni(stream, sslsock) == FAILURE) {
1646 return FAILURE;
1647 }
1648 #endif
1649
1650
1651 if (!sslsock->is_client) {
1652 init_server_reneg_limit(stream, sslsock);
1653 }
1654
1655 #ifdef SSL_MODE_RELEASE_BUFFERS
1656 do {
1657 long mode = SSL_get_mode(sslsock->ssl_handle);
1658 SSL_set_mode(sslsock->ssl_handle, mode | SSL_MODE_RELEASE_BUFFERS);
1659 } while (0);
1660 #endif
1661
1662 if (cparam->inputs.session) {
1663 if (cparam->inputs.session->ops != &php_openssl_socket_ops) {
1664 php_error_docref(NULL, E_WARNING, "supplied session stream must be an SSL enabled stream");
1665 } else if (((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle == NULL) {
1666 php_error_docref(NULL, E_WARNING, "supplied SSL session stream is not initialized");
1667 } else {
1668 SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle);
1669 }
1670 }
1671
1672 return SUCCESS;
1673 }
1674
1675
1676 static zend_array *capture_session_meta(SSL *ssl_handle)
1677 {
1678 zval meta_arr;
1679 char *proto_str;
1680 long proto = SSL_version(ssl_handle);
1681 const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_handle);
1682
1683 switch (proto) {
1684 #ifdef HAVE_TLS12
1685 case TLS1_2_VERSION:
1686 proto_str = "TLSv1.2";
1687 break;
1688 #endif
1689 #ifdef HAVE_TLS11
1690 case TLS1_1_VERSION:
1691 proto_str = "TLSv1.1";
1692 break;
1693 #endif
1694 case TLS1_VERSION:
1695 proto_str = "TLSv1";
1696 break;
1697 #ifdef HAVE_SSL3
1698 case SSL3_VERSION:
1699 proto_str = "SSLv3";
1700 break;
1701 #endif
1702 #ifdef HAVE_SSL2
1703 case SSL2_VERSION:
1704 proto_str = "SSLv2";
1705 break;
1706 #endif
1707 default: proto_str = "UNKNOWN";
1708 }
1709
1710 array_init(&meta_arr);
1711 add_assoc_string(&meta_arr, "protocol", proto_str);
1712 add_assoc_string(&meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher));
1713 add_assoc_long(&meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL));
1714 add_assoc_string(&meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher));
1715
1716 return Z_ARR(meta_arr);
1717 }
1718
1719
1720 static int capture_peer_certs(php_stream *stream, php_openssl_netstream_data_t *sslsock, X509 *peer_cert)
1721 {
1722 zval *val, zcert;
1723 int cert_captured = 0;
1724
1725 if (NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream),
1726 "ssl", "capture_peer_cert")) &&
1727 zend_is_true(val)
1728 ) {
1729 ZVAL_RES(&zcert, zend_register_resource(peer_cert, php_openssl_get_x509_list_id()));
1730 php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_certificate", &zcert);
1731 zval_ptr_dtor(&zcert);
1732 cert_captured = 1;
1733 }
1734
1735 if (NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream),
1736 "ssl", "capture_peer_cert_chain")) &&
1737 zend_is_true(val)
1738 ) {
1739 zval arr;
1740 STACK_OF(X509) *chain;
1741
1742 chain = SSL_get_peer_cert_chain(sslsock->ssl_handle);
1743
1744 if (chain && sk_X509_num(chain) > 0) {
1745 int i;
1746 array_init(&arr);
1747
1748 for (i = 0; i < sk_X509_num(chain); i++) {
1749 X509 *mycert = X509_dup(sk_X509_value(chain, i));
1750 ZVAL_RES(&zcert, zend_register_resource(mycert, php_openssl_get_x509_list_id()));
1751 add_next_index_zval(&arr, &zcert);
1752 }
1753
1754 } else {
1755 ZVAL_NULL(&arr);
1756 }
1757
1758 php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_certificate_chain", &arr);
1759 zval_ptr_dtor(&arr);
1760 }
1761
1762 return cert_captured;
1763 }
1764
1765
1766 static int php_openssl_enable_crypto(php_stream *stream,
1767 php_openssl_netstream_data_t *sslsock,
1768 php_stream_xport_crypto_param *cparam
1769 )
1770 {
1771 int n;
1772 int retry = 1;
1773 int cert_captured;
1774 X509 *peer_cert;
1775
1776 if (cparam->inputs.activate && !sslsock->ssl_active) {
1777 struct timeval start_time,
1778 *timeout;
1779 int blocked = sslsock->s.is_blocked,
1780 has_timeout = 0;
1781
1782 #ifdef HAVE_TLS_SNI
1783 if (sslsock->is_client) {
1784 enable_client_sni(stream, sslsock);
1785 }
1786 #endif
1787
1788 if (!sslsock->state_set) {
1789 if (sslsock->is_client) {
1790 SSL_set_connect_state(sslsock->ssl_handle);
1791 } else {
1792 SSL_set_accept_state(sslsock->ssl_handle);
1793 }
1794 sslsock->state_set = 1;
1795 }
1796
1797 if (SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0)) {
1798 sslsock->s.is_blocked = 0;
1799 }
1800
1801 timeout = sslsock->is_client ? &sslsock->connect_timeout : &sslsock->s.timeout;
1802 has_timeout = !sslsock->s.is_blocked && (timeout->tv_sec || timeout->tv_usec);
1803
1804 if (has_timeout) {
1805 gettimeofday(&start_time, NULL);
1806 }
1807
1808 do {
1809 struct timeval cur_time,
1810 elapsed_time;
1811
1812 if (sslsock->is_client) {
1813 n = SSL_connect(sslsock->ssl_handle);
1814 } else {
1815 n = SSL_accept(sslsock->ssl_handle);
1816 }
1817
1818 if (has_timeout) {
1819 gettimeofday(&cur_time, NULL);
1820 elapsed_time = subtract_timeval( cur_time, start_time );
1821
1822 if (compare_timeval( elapsed_time, *timeout) > 0) {
1823 php_error_docref(NULL, E_WARNING, "SSL: Handshake timed out");
1824 return -1;
1825 }
1826 }
1827
1828 if (n <= 0) {
1829
1830 retry = handle_ssl_error(stream, n, blocked);
1831 if (retry) {
1832
1833
1834 int err = SSL_get_error(sslsock->ssl_handle, n);
1835 struct timeval left_time;
1836
1837 if (has_timeout) {
1838 left_time = subtract_timeval( *timeout, elapsed_time );
1839 }
1840 php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
1841 (POLLIN|POLLPRI) : POLLOUT, has_timeout ? &left_time : NULL);
1842 }
1843 } else {
1844 retry = 0;
1845 }
1846 } while (retry);
1847
1848 if (sslsock->s.is_blocked != blocked && SUCCESS == php_set_sock_blocking(sslsock->s.socket, blocked)) {
1849 sslsock->s.is_blocked = blocked;
1850 }
1851
1852 if (n == 1) {
1853 peer_cert = SSL_get_peer_certificate(sslsock->ssl_handle);
1854 if (peer_cert && PHP_STREAM_CONTEXT(stream)) {
1855 cert_captured = capture_peer_certs(stream, sslsock, peer_cert);
1856 }
1857
1858 if (FAILURE == apply_peer_verification_policy(sslsock->ssl_handle, peer_cert, stream)) {
1859 SSL_shutdown(sslsock->ssl_handle);
1860 n = -1;
1861 } else {
1862 sslsock->ssl_active = 1;
1863
1864 if (PHP_STREAM_CONTEXT(stream)) {
1865 zval *val;
1866 if (NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream),
1867 "ssl", "capture_session_meta"))
1868 ) {
1869 php_error(E_DEPRECATED,
1870 "capture_session_meta is deprecated; its information is now available via stream_get_meta_data()"
1871 );
1872 }
1873
1874 if (val && zend_is_true(val)) {
1875 zval meta_arr;
1876 ZVAL_ARR(&meta_arr, capture_session_meta(sslsock->ssl_handle));
1877 php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "session_meta", &meta_arr);
1878 zval_ptr_dtor(&meta_arr);
1879 }
1880 }
1881 }
1882 } else if (errno == EAGAIN) {
1883 n = 0;
1884 } else {
1885 n = -1;
1886
1887 peer_cert = SSL_get_peer_certificate(sslsock->ssl_handle);
1888 if (peer_cert && PHP_STREAM_CONTEXT(stream)) {
1889 cert_captured = capture_peer_certs(stream, sslsock, peer_cert);
1890 }
1891 }
1892
1893 if (n && peer_cert && cert_captured == 0) {
1894 X509_free(peer_cert);
1895 }
1896
1897 return n;
1898
1899 } else if (!cparam->inputs.activate && sslsock->ssl_active) {
1900
1901 SSL_shutdown(sslsock->ssl_handle);
1902 sslsock->ssl_active = 0;
1903 }
1904
1905 return -1;
1906 }
1907
1908 static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t count)
1909 {
1910 return php_openssl_sockop_io( 1, stream, buf, count );
1911 }
1912
1913
1914 static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size_t count)
1915 {
1916 return php_openssl_sockop_io( 0, stream, (char*)buf, count );
1917 }
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927 static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, size_t count)
1928 {
1929 php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
1930
1931
1932 if (sslsock->ssl_active) {
1933 int retry = 1;
1934 struct timeval start_time;
1935 struct timeval *timeout = NULL;
1936 int began_blocked = sslsock->s.is_blocked;
1937 int has_timeout = 0;
1938 int nr_bytes = 0;
1939
1940
1941 if (count > INT_MAX) {
1942 count = INT_MAX;
1943 }
1944
1945
1946 if (began_blocked && &sslsock->s.timeout) {
1947 timeout = &sslsock->s.timeout;
1948 }
1949
1950 if (timeout && php_set_sock_blocking(sslsock->s.socket, 0) == SUCCESS) {
1951 sslsock->s.is_blocked = 0;
1952 }
1953
1954 if (!sslsock->s.is_blocked && timeout && (timeout->tv_sec || timeout->tv_usec)) {
1955 has_timeout = 1;
1956
1957 gettimeofday(&start_time, NULL);
1958 }
1959
1960
1961 do {
1962 struct timeval cur_time, elapsed_time, left_time;
1963
1964
1965 if (has_timeout) {
1966 gettimeofday(&cur_time, NULL);
1967
1968
1969 elapsed_time = subtract_timeval(cur_time, start_time);
1970
1971
1972 if (compare_timeval(elapsed_time, *timeout) > 0 ) {
1973
1974 if (began_blocked) {
1975 php_set_sock_blocking(sslsock->s.socket, 1);
1976 sslsock->s.is_blocked = 1;
1977 }
1978 sslsock->s.timeout_event = 1;
1979 return -1;
1980 }
1981 }
1982
1983
1984 if (read) {
1985 nr_bytes = SSL_read(sslsock->ssl_handle, buf, (int)count);
1986
1987 if (sslsock->reneg && sslsock->reneg->should_close) {
1988
1989 php_stream_xport_shutdown(stream, (stream_shutdown_t)SHUT_RDWR);
1990 nr_bytes = 0;
1991 stream->eof = 1;
1992 break;
1993 }
1994 } else {
1995 nr_bytes = SSL_write(sslsock->ssl_handle, buf, (int)count);
1996 }
1997
1998
1999 if (has_timeout) {
2000 left_time = subtract_timeval( *timeout, elapsed_time );
2001 }
2002
2003
2004 if (nr_bytes <= 0) {
2005
2006
2007 int err = SSL_get_error(sslsock->ssl_handle, nr_bytes );
2008 retry = handle_ssl_error(stream, nr_bytes, 0);
2009
2010
2011 if (errno == EAGAIN && err == SSL_ERROR_WANT_READ && read) {
2012 retry = 1;
2013 }
2014 if (errno == EAGAIN && err == SSL_ERROR_WANT_WRITE && read == 0) {
2015 retry = 1;
2016 }
2017
2018
2019 if (read) {
2020 stream->eof = (retry == 0 && errno != EAGAIN && !SSL_pending(sslsock->ssl_handle));
2021 }
2022
2023
2024 if (began_blocked == 0) {
2025 break;
2026 }
2027
2028
2029
2030
2031 if (retry) {
2032 if (read) {
2033 php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
2034 (POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
2035 } else {
2036 php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
2037 (POLLIN|POLLPRI) : (POLLOUT|POLLPRI), has_timeout ? &left_time : NULL);
2038 }
2039 }
2040 } else {
2041
2042 int err = SSL_get_error(sslsock->ssl_handle, nr_bytes);
2043
2044
2045 if (err == SSL_ERROR_NONE) {
2046 break;
2047 }
2048
2049
2050 if (began_blocked) {
2051 if (read) {
2052 php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
2053 (POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
2054 } else {
2055 php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
2056 (POLLIN|POLLPRI) : (POLLOUT|POLLPRI), has_timeout ? &left_time : NULL);
2057 }
2058 }
2059 }
2060
2061
2062 } while (retry);
2063
2064
2065 if (nr_bytes > 0) {
2066 php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), nr_bytes, 0);
2067 }
2068
2069
2070 if (began_blocked && php_set_sock_blocking(sslsock->s.socket, 1) == SUCCESS) {
2071 sslsock->s.is_blocked = 1;
2072 }
2073
2074 return 0 > nr_bytes ? 0 : nr_bytes;
2075 } else {
2076 size_t nr_bytes = 0;
2077
2078
2079
2080
2081 if (read) {
2082 nr_bytes = php_stream_socket_ops.read(stream, buf, count);
2083 } else {
2084 nr_bytes = php_stream_socket_ops.write(stream, buf, count);
2085 }
2086
2087 return nr_bytes;
2088 }
2089 }
2090
2091
2092 static struct timeval subtract_timeval( struct timeval a, struct timeval b )
2093 {
2094 struct timeval difference;
2095
2096 difference.tv_sec = a.tv_sec - b.tv_sec;
2097 difference.tv_usec = a.tv_usec - b.tv_usec;
2098
2099 if (a.tv_usec < b.tv_usec) {
2100 b.tv_sec -= 1L;
2101 b.tv_usec += 1000000L;
2102 }
2103
2104 return difference;
2105 }
2106
2107 static int compare_timeval( struct timeval a, struct timeval b )
2108 {
2109 if (a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec > b.tv_usec) ) {
2110 return 1;
2111 } else if( a.tv_sec == b.tv_sec && a.tv_usec == b.tv_usec ) {
2112 return 0;
2113 } else {
2114 return -1;
2115 }
2116 }
2117
2118 static int php_openssl_sockop_close(php_stream *stream, int close_handle)
2119 {
2120 php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
2121 #ifdef PHP_WIN32
2122 int n;
2123 #endif
2124 unsigned i;
2125
2126 if (close_handle) {
2127 if (sslsock->ssl_active) {
2128 SSL_shutdown(sslsock->ssl_handle);
2129 sslsock->ssl_active = 0;
2130 }
2131 if (sslsock->ssl_handle) {
2132 SSL_free(sslsock->ssl_handle);
2133 sslsock->ssl_handle = NULL;
2134 }
2135 if (sslsock->ctx) {
2136 SSL_CTX_free(sslsock->ctx);
2137 sslsock->ctx = NULL;
2138 }
2139 #ifdef PHP_WIN32
2140 if (sslsock->s.socket == -1)
2141 sslsock->s.socket = SOCK_ERR;
2142 #endif
2143 if (sslsock->s.socket != SOCK_ERR) {
2144 #ifdef PHP_WIN32
2145
2146 shutdown(sslsock->s.socket, SHUT_RD);
2147
2148
2149
2150
2151
2152
2153
2154 do {
2155 n = php_pollfd_for_ms(sslsock->s.socket, POLLOUT, 500);
2156 } while (n == -1 && php_socket_errno() == EINTR);
2157 #endif
2158 closesocket(sslsock->s.socket);
2159 sslsock->s.socket = SOCK_ERR;
2160 }
2161 }
2162
2163 if (sslsock->sni_certs) {
2164 for (i=0; i<sslsock->sni_cert_count; i++) {
2165 SSL_CTX_free(sslsock->sni_certs[i].ctx);
2166 pefree(sslsock->sni_certs[i].name, php_stream_is_persistent(stream));
2167 }
2168 pefree(sslsock->sni_certs, php_stream_is_persistent(stream));
2169 sslsock->sni_certs = NULL;
2170 }
2171
2172 if (sslsock->url_name) {
2173 pefree(sslsock->url_name, php_stream_is_persistent(stream));
2174 }
2175
2176 if (sslsock->reneg) {
2177 pefree(sslsock->reneg, php_stream_is_persistent(stream));
2178 }
2179
2180 pefree(sslsock, php_stream_is_persistent(stream));
2181
2182 return 0;
2183 }
2184
2185
2186 static int php_openssl_sockop_flush(php_stream *stream)
2187 {
2188 return php_stream_socket_ops.flush(stream);
2189 }
2190
2191
2192 static int php_openssl_sockop_stat(php_stream *stream, php_stream_statbuf *ssb)
2193 {
2194 return php_stream_socket_ops.stat(stream, ssb);
2195 }
2196
2197
2198 static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_netstream_data_t *sock,
2199 php_stream_xport_param *xparam STREAMS_DC)
2200 {
2201 int clisock;
2202
2203 xparam->outputs.client = NULL;
2204
2205 clisock = php_network_accept_incoming(sock->s.socket,
2206 xparam->want_textaddr ? &xparam->outputs.textaddr : NULL,
2207 xparam->want_addr ? &xparam->outputs.addr : NULL,
2208 xparam->want_addr ? &xparam->outputs.addrlen : NULL,
2209 xparam->inputs.timeout,
2210 xparam->want_errortext ? &xparam->outputs.error_text : NULL,
2211 &xparam->outputs.error_code
2212 );
2213
2214 if (clisock >= 0) {
2215 php_openssl_netstream_data_t *clisockdata;
2216
2217 clisockdata = emalloc(sizeof(*clisockdata));
2218
2219 if (clisockdata == NULL) {
2220 closesocket(clisock);
2221
2222 } else {
2223
2224 memset(clisockdata, 0, sizeof(*clisockdata));
2225 memcpy(clisockdata, sock, sizeof(clisockdata->s));
2226
2227 clisockdata->s.socket = clisock;
2228
2229 xparam->outputs.client = php_stream_alloc_rel(stream->ops, clisockdata, NULL, "r+");
2230 if (xparam->outputs.client) {
2231 xparam->outputs.client->ctx = stream->ctx;
2232 if (stream->ctx) {
2233 GC_REFCOUNT(stream->ctx)++;
2234 }
2235 }
2236 }
2237
2238 if (xparam->outputs.client && sock->enable_on_connect) {
2239
2240 if (sock->method & STREAM_CRYPTO_IS_CLIENT) {
2241 sock->method = ((sock->method >> 1) << 1);
2242 }
2243
2244 clisockdata->method = sock->method;
2245
2246 if (php_stream_xport_crypto_setup(xparam->outputs.client, clisockdata->method,
2247 NULL) < 0 || php_stream_xport_crypto_enable(
2248 xparam->outputs.client, 1) < 0) {
2249 php_error_docref(NULL, E_WARNING, "Failed to enable crypto");
2250
2251 php_stream_close(xparam->outputs.client);
2252 xparam->outputs.client = NULL;
2253 xparam->outputs.returncode = -1;
2254 }
2255 }
2256 }
2257
2258 return xparam->outputs.client == NULL ? -1 : 0;
2259 }
2260
2261 static int php_openssl_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam)
2262 {
2263 php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
2264 php_stream_xport_crypto_param *cparam = (php_stream_xport_crypto_param *)ptrparam;
2265 php_stream_xport_param *xparam = (php_stream_xport_param *)ptrparam;
2266
2267 switch (option) {
2268 case PHP_STREAM_OPTION_META_DATA_API:
2269 if (sslsock->ssl_active) {
2270 zval tmp;
2271 char *proto_str;
2272 const SSL_CIPHER *cipher;
2273
2274 array_init(&tmp);
2275
2276 switch (SSL_version(sslsock->ssl_handle)) {
2277 #ifdef HAVE_TLS12
2278 case TLS1_2_VERSION: proto_str = "TLSv1.2"; break;
2279 #endif
2280 #ifdef HAVE_TLS11
2281 case TLS1_1_VERSION: proto_str = "TLSv1.1"; break;
2282 #endif
2283 case TLS1_VERSION: proto_str = "TLSv1"; break;
2284 #ifdef HAVE_SSL3
2285 case SSL3_VERSION: proto_str = "SSLv3"; break;
2286 #endif
2287 #ifdef HAVE_SSL2
2288 case SSL2_VERSION: proto_str = "SSLv2"; break;
2289 #endif
2290 default: proto_str = "UNKNOWN";
2291 }
2292
2293 cipher = SSL_get_current_cipher(sslsock->ssl_handle);
2294
2295 add_assoc_string(&tmp, "protocol", proto_str);
2296 add_assoc_string(&tmp, "cipher_name", (char *) SSL_CIPHER_get_name(cipher));
2297 add_assoc_long(&tmp, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL));
2298 add_assoc_string(&tmp, "cipher_version", SSL_CIPHER_get_version(cipher));
2299
2300 #ifdef HAVE_TLS_ALPN
2301 {
2302 const unsigned char *alpn_proto = NULL;
2303 unsigned int alpn_proto_len = 0;
2304
2305 SSL_get0_alpn_selected(sslsock->ssl_handle, &alpn_proto, &alpn_proto_len);
2306 if (alpn_proto) {
2307 add_assoc_stringl(&tmp, "alpn_protocol", (char *)alpn_proto, alpn_proto_len);
2308 }
2309 }
2310 #endif
2311 add_assoc_zval((zval *)ptrparam, "crypto", &tmp);
2312 }
2313
2314 add_assoc_bool((zval *)ptrparam, "timed_out", sslsock->s.timeout_event);
2315 add_assoc_bool((zval *)ptrparam, "blocked", sslsock->s.is_blocked);
2316 add_assoc_bool((zval *)ptrparam, "eof", stream->eof);
2317
2318 return PHP_STREAM_OPTION_RETURN_OK;
2319
2320 case PHP_STREAM_OPTION_CHECK_LIVENESS:
2321 {
2322 struct timeval tv;
2323 char buf;
2324 int alive = 1;
2325
2326 if (value == -1) {
2327 if (sslsock->s.timeout.tv_sec == -1) {
2328 #ifdef _WIN32
2329 tv.tv_sec = (long)FG(default_socket_timeout);
2330 #else
2331 tv.tv_sec = (time_t)FG(default_socket_timeout);
2332 #endif
2333 tv.tv_usec = 0;
2334 } else {
2335 tv = sslsock->connect_timeout;
2336 }
2337 } else {
2338 tv.tv_sec = value;
2339 tv.tv_usec = 0;
2340 }
2341
2342 if (sslsock->s.socket == -1) {
2343 alive = 0;
2344 } else if (php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) {
2345 if (sslsock->ssl_active) {
2346 int n;
2347
2348 do {
2349 n = SSL_peek(sslsock->ssl_handle, &buf, sizeof(buf));
2350 if (n <= 0) {
2351 int err = SSL_get_error(sslsock->ssl_handle, n);
2352
2353 if (err == SSL_ERROR_SYSCALL) {
2354 alive = php_socket_errno() == EAGAIN;
2355 break;
2356 }
2357
2358 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2359
2360 continue;
2361 }
2362
2363
2364 alive = 0;
2365 }
2366
2367
2368 break;
2369 } while (1);
2370 } else if (0 == recv(sslsock->s.socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) {
2371 alive = 0;
2372 }
2373 }
2374 return alive ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
2375 }
2376
2377 case PHP_STREAM_OPTION_CRYPTO_API:
2378
2379 switch(cparam->op) {
2380
2381 case STREAM_XPORT_CRYPTO_OP_SETUP:
2382 cparam->outputs.returncode = php_openssl_setup_crypto(stream, sslsock, cparam);
2383 return PHP_STREAM_OPTION_RETURN_OK;
2384 break;
2385 case STREAM_XPORT_CRYPTO_OP_ENABLE:
2386 cparam->outputs.returncode = php_openssl_enable_crypto(stream, sslsock, cparam);
2387 return PHP_STREAM_OPTION_RETURN_OK;
2388 break;
2389 default:
2390
2391 break;
2392 }
2393
2394 break;
2395
2396 case PHP_STREAM_OPTION_XPORT_API:
2397 switch(xparam->op) {
2398
2399 case STREAM_XPORT_OP_CONNECT:
2400 case STREAM_XPORT_OP_CONNECT_ASYNC:
2401
2402
2403 php_stream_socket_ops.set_option(stream, option, value, ptrparam);
2404
2405 if ((sslsock->enable_on_connect) &&
2406 ((xparam->outputs.returncode == 0) ||
2407 (xparam->op == STREAM_XPORT_OP_CONNECT_ASYNC &&
2408 xparam->outputs.returncode == 1 && xparam->outputs.error_code == EINPROGRESS)))
2409 {
2410 if (php_stream_xport_crypto_setup(stream, sslsock->method, NULL) < 0 ||
2411 php_stream_xport_crypto_enable(stream, 1) < 0) {
2412 php_error_docref(NULL, E_WARNING, "Failed to enable crypto");
2413 xparam->outputs.returncode = -1;
2414 }
2415 }
2416 return PHP_STREAM_OPTION_RETURN_OK;
2417
2418 case STREAM_XPORT_OP_ACCEPT:
2419
2420
2421 xparam->outputs.returncode = php_openssl_tcp_sockop_accept(stream, sslsock, xparam STREAMS_CC);
2422
2423
2424 return PHP_STREAM_OPTION_RETURN_OK;
2425
2426 default:
2427
2428 break;
2429 }
2430 }
2431
2432 return php_stream_socket_ops.set_option(stream, option, value, ptrparam);
2433 }
2434
2435 static int php_openssl_sockop_cast(php_stream *stream, int castas, void **ret)
2436 {
2437 php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
2438
2439 switch(castas) {
2440 case PHP_STREAM_AS_STDIO:
2441 if (sslsock->ssl_active) {
2442 return FAILURE;
2443 }
2444 if (ret) {
2445 *ret = fdopen(sslsock->s.socket, stream->mode);
2446 if (*ret) {
2447 return SUCCESS;
2448 }
2449 return FAILURE;
2450 }
2451 return SUCCESS;
2452
2453 case PHP_STREAM_AS_FD_FOR_SELECT:
2454 if (ret) {
2455 size_t pending;
2456 if (stream->writepos == stream->readpos
2457 && sslsock->ssl_active
2458 && (pending = (size_t)SSL_pending(sslsock->ssl_handle)) > 0) {
2459 php_stream_fill_read_buffer(stream, pending < stream->chunk_size
2460 ? pending
2461 : stream->chunk_size);
2462 }
2463
2464 *(php_socket_t *)ret = sslsock->s.socket;
2465 }
2466 return SUCCESS;
2467
2468 case PHP_STREAM_AS_FD:
2469 case PHP_STREAM_AS_SOCKETD:
2470 if (sslsock->ssl_active) {
2471 return FAILURE;
2472 }
2473 if (ret) {
2474 *(php_socket_t *)ret = sslsock->s.socket;
2475 }
2476 return SUCCESS;
2477 default:
2478 return FAILURE;
2479 }
2480 }
2481
2482 php_stream_ops php_openssl_socket_ops = {
2483 php_openssl_sockop_write, php_openssl_sockop_read,
2484 php_openssl_sockop_close, php_openssl_sockop_flush,
2485 "tcp_socket/ssl",
2486 NULL,
2487 php_openssl_sockop_cast,
2488 php_openssl_sockop_stat,
2489 php_openssl_sockop_set_option,
2490 };
2491
2492 static zend_long get_crypto_method(php_stream_context *ctx, zend_long crypto_method)
2493 {
2494 zval *val;
2495
2496 if (ctx && (val = php_stream_context_get_option(ctx, "ssl", "crypto_method")) != NULL) {
2497 convert_to_long_ex(val);
2498 crypto_method = (zend_long)Z_LVAL_P(val);
2499 crypto_method |= STREAM_CRYPTO_IS_CLIENT;
2500 }
2501
2502 return crypto_method;
2503 }
2504
2505 static char *get_url_name(const char *resourcename, size_t resourcenamelen, int is_persistent)
2506 {
2507 php_url *url;
2508
2509 if (!resourcename) {
2510 return NULL;
2511 }
2512
2513 url = php_url_parse_ex(resourcename, resourcenamelen);
2514 if (!url) {
2515 return NULL;
2516 }
2517
2518 if (url->host) {
2519 const char * host = url->host;
2520 char * url_name = NULL;
2521 size_t len = strlen(host);
2522
2523
2524 while (len && host[len-1] == '.') {
2525 --len;
2526 }
2527
2528 if (len) {
2529 url_name = pestrndup(host, len, is_persistent);
2530 }
2531
2532 php_url_free(url);
2533 return url_name;
2534 }
2535
2536 php_url_free(url);
2537 return NULL;
2538 }
2539
2540 php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen,
2541 const char *resourcename, size_t resourcenamelen,
2542 const char *persistent_id, int options, int flags,
2543 struct timeval *timeout,
2544 php_stream_context *context STREAMS_DC)
2545 {
2546 php_stream *stream = NULL;
2547 php_openssl_netstream_data_t *sslsock = NULL;
2548
2549 sslsock = pemalloc(sizeof(php_openssl_netstream_data_t), persistent_id ? 1 : 0);
2550 memset(sslsock, 0, sizeof(*sslsock));
2551
2552 sslsock->s.is_blocked = 1;
2553
2554 #ifdef _WIN32
2555 sslsock->s.timeout.tv_sec = (long)FG(default_socket_timeout);
2556 #else
2557 sslsock->s.timeout.tv_sec = (time_t)FG(default_socket_timeout);
2558 #endif
2559 sslsock->s.timeout.tv_usec = 0;
2560
2561
2562 sslsock->connect_timeout.tv_sec = timeout->tv_sec;
2563 sslsock->connect_timeout.tv_usec = timeout->tv_usec;
2564
2565
2566
2567 sslsock->s.socket = -1;
2568
2569
2570 sslsock->ctx = NULL;
2571
2572 stream = php_stream_alloc_rel(&php_openssl_socket_ops, sslsock, persistent_id, "r+");
2573
2574 if (stream == NULL) {
2575 pefree(sslsock, persistent_id ? 1 : 0);
2576 return NULL;
2577 }
2578
2579 if (strncmp(proto, "ssl", protolen) == 0) {
2580 sslsock->enable_on_connect = 1;
2581 sslsock->method = get_crypto_method(context, STREAM_CRYPTO_METHOD_ANY_CLIENT);
2582 } else if (strncmp(proto, "sslv2", protolen) == 0) {
2583 #ifdef HAVE_SSL2
2584 sslsock->enable_on_connect = 1;
2585 sslsock->method = STREAM_CRYPTO_METHOD_SSLv2_CLIENT;
2586 #else
2587 php_error_docref(NULL, E_WARNING, "SSLv2 support is not compiled into the OpenSSL library against which PHP is linked");
2588 php_stream_close(stream);
2589 return NULL;
2590 #endif
2591 } else if (strncmp(proto, "sslv3", protolen) == 0) {
2592 #ifdef HAVE_SSL3
2593 sslsock->enable_on_connect = 1;
2594 sslsock->method = STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
2595 #else
2596 php_error_docref(NULL, E_WARNING, "SSLv3 support is not compiled into the OpenSSL library against which PHP is linked");
2597 php_stream_close(stream);
2598 return NULL;
2599 #endif
2600 } else if (strncmp(proto, "tls", protolen) == 0) {
2601 sslsock->enable_on_connect = 1;
2602 sslsock->method = get_crypto_method(context, STREAM_CRYPTO_METHOD_TLS_CLIENT);
2603 } else if (strncmp(proto, "tlsv1.0", protolen) == 0) {
2604 sslsock->enable_on_connect = 1;
2605 sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT;
2606 } else if (strncmp(proto, "tlsv1.1", protolen) == 0) {
2607 #ifdef HAVE_TLS11
2608 sslsock->enable_on_connect = 1;
2609 sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
2610 #else
2611 php_error_docref(NULL, E_WARNING, "TLSv1.1 support is not compiled into the OpenSSL library against which PHP is linked");
2612 php_stream_close(stream);
2613 return NULL;
2614 #endif
2615 } else if (strncmp(proto, "tlsv1.2", protolen) == 0) {
2616 #ifdef HAVE_TLS12
2617 sslsock->enable_on_connect = 1;
2618 sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
2619 #else
2620 php_error_docref(NULL, E_WARNING, "TLSv1.2 support is not compiled into the OpenSSL library against which PHP is linked");
2621 php_stream_close(stream);
2622 return NULL;
2623 #endif
2624 }
2625
2626 sslsock->url_name = get_url_name(resourcename, resourcenamelen, !!persistent_id);
2627
2628 return stream;
2629 }
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640