diff options
Diffstat (limited to 'ext/openssl/xp_ssl.c')
-rw-r--r-- | ext/openssl/xp_ssl.c | 317 |
1 files changed, 142 insertions, 175 deletions
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 6a10366cd0..f706e0d5a2 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -67,15 +67,15 @@ #define STREAM_CRYPTO_METHOD_TLSv1_2 (1<<5) /* Simplify ssl context option retrieval */ -#define GET_VER_OPT(name) (stream->context && SUCCESS == php_stream_context_get_option(stream->context, "ssl", name, &val)) -#define GET_VER_OPT_STRING(name, str) if (GET_VER_OPT(name)) { convert_to_string_ex(val); str = Z_STRVAL_PP(val); } -#define GET_VER_OPT_LONG(name, num) if (GET_VER_OPT(name)) { convert_to_long_ex(val); num = Z_LVAL_PP(val); } +#define GET_VER_OPT(name) (PHP_STREAM_CONTEXT(stream) && (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", name)) != NULL) +#define GET_VER_OPT_STRING(name, str) if (GET_VER_OPT(name)) { convert_to_string_ex(val); str = Z_STRVAL_P(val); } +#define GET_VER_OPT_LONG(name, num) if (GET_VER_OPT(name)) { convert_to_long_ex(val); num = Z_LVAL_P(val); } /* Used for peer verification in windows */ #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))) extern php_stream* php_openssl_get_stream_from_ssl_handle(const SSL *ssl); -extern int php_openssl_x509_fingerprint(X509 *peer, const char *method, zend_bool raw, char **out, int *out_len TSRMLS_DC); +extern zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, zend_bool raw TSRMLS_DC); extern int php_openssl_get_ssl_stream_data_index(); extern int php_openssl_get_x509_list_id(void); @@ -121,24 +121,20 @@ typedef struct _php_openssl_netstream_data_t { * in an error condition arising from a network connection problem */ static int is_http_stream_talking_to_iis(php_stream *stream TSRMLS_DC) /* {{{ */ { - if (stream->wrapperdata && stream->wrapper && strcasecmp(stream->wrapper->wops->label, "HTTP") == 0) { + if (Z_TYPE(stream->wrapperdata) == IS_ARRAY && stream->wrapper && strcasecmp(stream->wrapper->wops->label, "HTTP") == 0) { /* the wrapperdata is an array zval containing the headers */ - zval **tmp; + zval *tmp; #define SERVER_MICROSOFT_IIS "Server: Microsoft-IIS" #define SERVER_GOOGLE "Server: GFE/" - zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream->wrapperdata)); - while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(stream->wrapperdata), (void**)&tmp)) { - - if (strncasecmp(Z_STRVAL_PP(tmp), SERVER_MICROSOFT_IIS, sizeof(SERVER_MICROSOFT_IIS)-1) == 0) { + ZEND_HASH_FOREACH_VAL(Z_ARRVAL(stream->wrapperdata), tmp) { + if (strncasecmp(Z_STRVAL_P(tmp), SERVER_MICROSOFT_IIS, sizeof(SERVER_MICROSOFT_IIS)-1) == 0) { return 1; - } else if (strncasecmp(Z_STRVAL_PP(tmp), SERVER_GOOGLE, sizeof(SERVER_GOOGLE)-1) == 0) { + } else if (strncasecmp(Z_STRVAL_P(tmp), SERVER_GOOGLE, sizeof(SERVER_GOOGLE)-1) == 0) { return 1; } - - zend_hash_move_forward(Z_ARRVAL_P(stream->wrapperdata)); - } + } ZEND_HASH_FOREACH_END(); } return 0; } @@ -203,7 +199,7 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes, zend_bool is_init do { /* NULL is automatically added */ ERR_error_string_n(ecode, esbuf, sizeof(esbuf)); - if (ebuf.c) { + if (ebuf.s) { smart_str_appendc(&ebuf, '\n'); } smart_str_appends(&ebuf, esbuf); @@ -214,9 +210,9 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes, zend_bool is_init php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL operation failed with code %d. %s%s", err, - ebuf.c ? "OpenSSL Error messages:\n" : "", - ebuf.c ? ebuf.c : ""); - if (ebuf.c) { + ebuf.s ? "OpenSSL Error messages:\n" : "", + ebuf.s ? ebuf.s->val : ""); + if (ebuf.s) { smart_str_free(&ebuf); } } @@ -233,7 +229,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */ php_stream *stream; SSL *ssl; int err, depth, ret; - zval **val; + zval *val; unsigned long allowed_depth = OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH; TSRMLS_FETCH(); @@ -251,7 +247,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */ /* if allow_self_signed is set, make sure that verification succeeds */ if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && GET_VER_OPT("allow_self_signed") && - zend_is_true(*val TSRMLS_CC) + zend_is_true(val TSRMLS_CC) ) { ret = 1; } @@ -269,13 +265,13 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */ static int php_x509_fingerprint_cmp(X509 *peer, const char *method, const char *expected TSRMLS_DC) { - char *fingerprint; - int fingerprint_len; + zend_string *fingerprint; int result = -1; - if (php_openssl_x509_fingerprint(peer, method, 0, &fingerprint, &fingerprint_len TSRMLS_CC) == SUCCESS) { - result = strcmp(expected, fingerprint); - efree(fingerprint); + fingerprint = php_openssl_x509_fingerprint(peer, method, 0 TSRMLS_CC); + if (fingerprint) { + result = strcmp(expected, fingerprint->val); + STR_RELEASE(fingerprint); } return result; @@ -298,25 +294,16 @@ static zend_bool php_x509_fingerprint_match(X509 *peer, zval *val TSRMLS_DC) return method && php_x509_fingerprint_cmp(peer, method, Z_STRVAL_P(val) TSRMLS_CC) == 0; } else if (Z_TYPE_P(val) == IS_ARRAY) { - HashPosition pos; - zval **current; - char *key; - uint key_len; - ulong key_index; - - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(val), &pos); - zend_hash_get_current_data_ex(Z_ARRVAL_P(val), (void **)¤t, &pos) == SUCCESS; - zend_hash_move_forward_ex(Z_ARRVAL_P(val), &pos) - ) { - int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(val), &key, &key_len, &key_index, 0, &pos); + zval *current; + zend_string *key; - if (key_type == HASH_KEY_IS_STRING - && Z_TYPE_PP(current) == IS_STRING - && php_x509_fingerprint_cmp(peer, key, Z_STRVAL_PP(current) TSRMLS_CC) != 0 + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(val), key, current) { + if (key && Z_TYPE_P(current) == IS_STRING + && php_x509_fingerprint_cmp(peer, key->val, Z_STRVAL_P(current) TSRMLS_CC) != 0 ) { return 0; } - } + } ZEND_HASH_FOREACH_END(); return 1; } return 0; @@ -419,7 +406,7 @@ static zend_bool matches_common_name(X509 *peer, const char *subject_name TSRMLS static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC) /* {{{ */ { - zval **val = NULL; + zval *val = NULL; char *peer_name = NULL; int err, must_verify_peer, @@ -430,15 +417,15 @@ static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stre php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract; must_verify_peer = GET_VER_OPT("verify_peer") - ? zend_is_true(*val TSRMLS_CC) + ? zend_is_true(val TSRMLS_CC) : sslsock->is_client; has_cnmatch_ctx_opt = GET_VER_OPT("CN_match"); must_verify_peer_name = (has_cnmatch_ctx_opt || GET_VER_OPT("verify_peer_name")) - ? zend_is_true(*val TSRMLS_CC) + ? zend_is_true(val TSRMLS_CC) : sslsock->is_client; - must_verify_fingerprint = (GET_VER_OPT("peer_fingerprint") && zend_is_true(*val TSRMLS_CC)); + must_verify_fingerprint = (GET_VER_OPT("peer_fingerprint") && zend_is_true(val TSRMLS_CC)); if ((must_verify_peer || must_verify_peer_name || must_verify_fingerprint) && peer == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not get peer certificate"); @@ -453,7 +440,7 @@ static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stre /* fine */ break; case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - if (GET_VER_OPT("allow_self_signed") && zend_is_true(*val TSRMLS_CC)) { + if (GET_VER_OPT("allow_self_signed") && zend_is_true(val TSRMLS_CC)) { /* allowed */ break; } @@ -470,8 +457,8 @@ static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stre /* If a peer_fingerprint match is required this trumps peer and peer_name verification */ if (must_verify_fingerprint) { - if (Z_TYPE_PP(val) == IS_STRING || Z_TYPE_PP(val) == IS_ARRAY) { - if (!php_x509_fingerprint_match(peer, *val TSRMLS_CC)) { + if (Z_TYPE_P(val) == IS_STRING || Z_TYPE_P(val) == IS_ARRAY) { + if (!php_x509_fingerprint_match(peer, val TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer fingerprint doesn't match" ); @@ -519,16 +506,16 @@ static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stre static int passwd_callback(char *buf, int num, int verify, void *data) /* {{{ */ { php_stream *stream = (php_stream *)data; - zval **val = NULL; + zval *val = NULL; char *passphrase = NULL; /* TODO: could expand this to make a callback into PHP user-space */ GET_VER_OPT_STRING("passphrase", passphrase); if (passphrase) { - if (Z_STRLEN_PP(val) < num - 1) { - memcpy(buf, Z_STRVAL_PP(val), Z_STRLEN_PP(val)+1); - return Z_STRLEN_PP(val); + if (Z_STRLEN_P(val) < num - 1) { + memcpy(buf, Z_STRVAL_P(val), Z_STRLEN_P(val)+1); + return Z_STRLEN_P(val); } } return 0; @@ -782,7 +769,7 @@ static long load_stream_cafile(X509_STORE *cert_store, const char *cafile TSRMLS static int enable_peer_verification(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */ { - zval **val = NULL; + zval *val = NULL; char *cafile = NULL; char *capath = NULL; @@ -790,12 +777,12 @@ static int enable_peer_verification(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) GET_VER_OPT_STRING("capath", capath); if (!cafile) { - cafile = zend_ini_string("openssl.cafile", sizeof("openssl.cafile"), 0); + cafile = zend_ini_string("openssl.cafile", sizeof("openssl.cafile")-1, 0); cafile = strlen(cafile) ? cafile : NULL; } if (!capath) { - capath = zend_ini_string("openssl.capath", sizeof("openssl.capath"), 0); + capath = zend_ini_string("openssl.capath", sizeof("openssl.capath")-1, 0); capath = strlen(capath) ? capath : NULL; } @@ -835,7 +822,7 @@ static void disable_peer_verification(SSL_CTX *ctx, php_stream *stream TSRMLS_DC static int set_local_cert(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */ { - zval **val = NULL; + zval *val = NULL; char *certfile = NULL; GET_VER_OPT_STRING("local_cert", certfile); @@ -992,37 +979,32 @@ static void limit_handshake_reneg(const SSL *ssl) /* {{{ */ /* The token level exceeds our allowed limit */ if (sslsock->reneg->tokens > sslsock->reneg->limit) { - zval **val; + zval *val; TSRMLS_FETCH(); sslsock->reneg->should_close = 1; - if (stream->context && SUCCESS == php_stream_context_get_option(stream->context, - "ssl", "reneg_limit_callback", &val) + if (PHP_STREAM_CONTEXT(stream) && (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), + "ssl", "reneg_limit_callback")) != NULL ) { - zval *param, **params[1], *retval; + zval param, retval; - MAKE_STD_ZVAL(param); - php_stream_to_zval(stream, param); - params[0] = ¶m; + php_stream_to_zval(stream, ¶m); /* Closing the stream inside this callback would segfault! */ stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; - if (FAILURE == call_user_function_ex(EG(function_table), NULL, *val, &retval, 1, params, 0, NULL TSRMLS_CC)) { + if (FAILURE == call_user_function_ex(EG(function_table), NULL, val, &retval, 1, ¶m, 0, NULL TSRMLS_CC)) { php_error(E_WARNING, "SSL: failed invoking reneg limit notification callback"); } stream->flags ^= PHP_STREAM_FLAG_NO_FCLOSE; /* If the reneg_limit_callback returned true don't auto-close */ - if (retval != NULL && Z_TYPE_P(retval) == IS_BOOL && Z_BVAL_P(retval) == 1) { + if (Z_TYPE(retval) == IS_TRUE) { sslsock->reneg->should_close = 0; } - FREE_ZVAL(param); - if (retval != NULL) { - zval_ptr_dtor(&retval); - } + zval_ptr_dtor(&retval); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL: client-initiated handshake rate limit exceeded by peer"); @@ -1042,16 +1024,16 @@ static void info_callback(const SSL *ssl, int where, int ret) /* {{{ */ static void init_server_reneg_limit(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ { - zval **val; + zval *val; long limit = OPENSSL_DEFAULT_RENEG_LIMIT; long window = OPENSSL_DEFAULT_RENEG_WINDOW; - if (stream->context && - SUCCESS == php_stream_context_get_option(stream->context, - "ssl", "reneg_limit", &val) + if (PHP_STREAM_CONTEXT(stream) && + NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), + "ssl", "reneg_limit")) ) { - convert_to_long(*val); - limit = Z_LVAL_PP(val); + convert_to_long(val); + limit = Z_LVAL_P(val); } /* No renegotiation rate-limiting */ @@ -1059,12 +1041,12 @@ static void init_server_reneg_limit(php_stream *stream, php_openssl_netstream_da return; } - if (stream->context && - SUCCESS == php_stream_context_get_option(stream->context, - "ssl", "reneg_window", &val) + if (PHP_STREAM_CONTEXT(stream) && + NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), + "ssl", "reneg_window")) ) { - convert_to_long(*val); - window = Z_LVAL_PP(val); + convert_to_long(val); + window = Z_LVAL_P(val); } sslsock->reneg = (void*)pemalloc(sizeof(php_openssl_handshake_bucket_t), @@ -1083,12 +1065,12 @@ static void init_server_reneg_limit(php_stream *stream, php_openssl_netstream_da static int set_server_rsa_key(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */ { - zval ** val; + zval *val; int rsa_key_size; RSA* rsa; - if (php_stream_context_get_option(stream->context, "ssl", "rsa_key_size", &val) == SUCCESS) { - rsa_key_size = (int) Z_LVAL_PP(val); + if ((val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "rsa_key_size")) != NULL) { + rsa_key_size = (int) Z_LVAL_P(val); if ((rsa_key_size != 1) && (rsa_key_size & (rsa_key_size - 1))) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "RSA key size requires a power of 2: %d", rsa_key_size); rsa_key_size = 2048; @@ -1146,14 +1128,14 @@ static int set_server_dh_param(SSL_CTX *ctx, char *dh_path TSRMLS_DC) /* {{{ */ #ifdef HAVE_ECDH static int set_server_ecdh_curve(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */ { - zval **val; + zval *val; int curve_nid; char *curve_str; EC_KEY *ecdh; - if (php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val) == SUCCESS) { + if ((val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "ecdh_curve")) != NULL) { convert_to_string_ex(val); - curve_str = Z_STRVAL_PP(val); + curve_str = Z_STRVAL_P(val); curve_nid = OBJ_sn2nid(curve_str); if (curve_nid == NID_undef) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid ECDH curve: %s", curve_str); @@ -1181,7 +1163,7 @@ static int set_server_ecdh_curve(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* static int set_server_specific_opts(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */ { - zval **val; + zval *val; long ssl_ctx_options = SSL_CTX_get_options(ctx); #ifdef HAVE_ECDH @@ -1189,7 +1171,7 @@ static int set_server_specific_opts(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) return FAILURE; } #else - if (SUCCESS == php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val)) { + if (SUCCESS == php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "ecdh_curve", &val)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "ECDH curve support not compiled into the OpenSSL lib against which PHP is linked"); @@ -1197,9 +1179,9 @@ static int set_server_specific_opts(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) } #endif - if (php_stream_context_get_option(stream->context, "ssl", "dh_param", &val) == SUCCESS) { + if ((val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "dh_param")) != NULL) { convert_to_string_ex(val); - if (FAILURE == set_server_dh_param(ctx, Z_STRVAL_PP(val) TSRMLS_CC)) { + if (FAILURE == set_server_dh_param(ctx, Z_STRVAL_P(val) TSRMLS_CC)) { return FAILURE; } } @@ -1208,25 +1190,24 @@ static int set_server_specific_opts(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) return FAILURE; } - if (SUCCESS == php_stream_context_get_option( - stream->context, "ssl", "honor_cipher_order", &val) && - zend_is_true(*val TSRMLS_CC) + if (NULL != (val = php_stream_context_get_option( + PHP_STREAM_CONTEXT(stream), "ssl", "honor_cipher_order")) && + zend_is_true(val TSRMLS_CC) ) { ssl_ctx_options |= SSL_OP_CIPHER_SERVER_PREFERENCE; } - if (SUCCESS == php_stream_context_get_option( - stream->context, "ssl", "single_dh_use", &val) && - zend_is_true(*val TSRMLS_CC) + if (NULL != (val = php_stream_context_get_option( + PHP_STREAM_CONTEXT(stream), "ssl", "single_dh_use")) && + zend_is_true(val TSRMLS_CC) ) { ssl_ctx_options |= SSL_OP_SINGLE_DH_USE; } #ifdef HAVE_ECDH - if (SUCCESS == php_stream_context_get_option( - stream->context, "ssl", "single_ecdh_use", &val) && - zend_is_true(*val TSRMLS_CC) - ) { + if (NULL != (val = php_stream_context_get_option( + PHP_STREAM_CONTEXT(stream), "ssl", "single_ecdh_use")) && + zend_is_true(val TSRMLS_CC)) { ssl_ctx_options |= SSL_OP_SINGLE_ECDH_USE; } #endif @@ -1271,19 +1252,16 @@ static int server_sni_callback(SSL *ssl_handle, int *al, void *arg) /* {{{ */ static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock TSRMLS_DC) { - zval **val; - zval **current; - char *key; - uint key_len; + zval *val; + zval *current; + zend_string *key; ulong key_index; - int key_type; - HashPosition pos; int i = 0; char resolved_path_buff[MAXPATHLEN]; SSL_CTX *ctx; /* If the stream ctx disables SNI we're finished here */ - if (GET_VER_OPT("SNI_enabled") && !zend_is_true(*val TSRMLS_CC)) { + if (GET_VER_OPT("SNI_enabled") && !zend_is_true(val TSRMLS_CC)) { return SUCCESS; } @@ -1292,14 +1270,14 @@ static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *s return SUCCESS; } - if (Z_TYPE_PP(val) != IS_ARRAY) { + if (Z_TYPE_P(val) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SNI_server_certs requires an array mapping host names to cert paths" ); return FAILURE; } - sslsock->sni_cert_count = zend_hash_num_elements(Z_ARRVAL_PP(val)); + sslsock->sni_cert_count = zend_hash_num_elements(Z_ARRVAL_P(val)); if (sslsock->sni_cert_count == 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SNI_server_certs host cert array must not be empty" @@ -1311,19 +1289,15 @@ static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *s sizeof(php_openssl_sni_cert_t), 0, php_stream_is_persistent(stream) ); - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(val), &pos); - zend_hash_get_current_data_ex(Z_ARRVAL_PP(val), (void **)¤t, &pos) == SUCCESS; - zend_hash_move_forward_ex(Z_ARRVAL_PP(val), &pos) - ) { - key_type = zend_hash_get_current_key_ex(Z_ARRVAL_PP(val), &key, &key_len, &key_index, 0, &pos); - if (key_type != HASH_KEY_IS_STRING) { + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(val), key_index,key, current) { + if (!key) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SNI_server_certs array requires string host name keys" ); return FAILURE; } - if (VCWD_REALPATH(Z_STRVAL_PP(current), resolved_path_buff)) { + if (VCWD_REALPATH(Z_STRVAL_P(current), resolved_path_buff)) { /* The hello method is not inherited by SSL structs when assigning a new context * inside the SNI callback, so the just use SSLv23 */ ctx = SSL_CTX_new(SSLv23_server_method()); @@ -1345,18 +1319,18 @@ static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *s SSL_CTX_free(ctx); return FAILURE; } else { - sslsock->sni_certs[i].name = pestrdup(key, php_stream_is_persistent(stream)); + sslsock->sni_certs[i].name = pestrdup(key->val, php_stream_is_persistent(stream)); sslsock->sni_certs[i].ctx = ctx; ++i; } } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed setting local cert chain file `%s'; file not found", - Z_STRVAL_PP(current) + Z_STRVAL_P(current) ); return FAILURE; } - } + } ZEND_HASH_FOREACH_END(); SSL_CTX_set_tlsext_servername_callback(sslsock->ctx, server_sni_callback); @@ -1365,11 +1339,11 @@ static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *s static void enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock TSRMLS_DC) /* {{{ */ { - zval **val; + zval *val; char *sni_server_name; /* If SNI is explicitly disabled we're finished here */ - if (GET_VER_OPT("SNI_enabled") && !zend_is_true(*val TSRMLS_CC)) { + if (GET_VER_OPT("SNI_enabled") && !zend_is_true(val TSRMLS_CC)) { return; } @@ -1398,7 +1372,7 @@ int php_openssl_setup_crypto(php_stream *stream, long ssl_ctx_options; long method_flags; char *cipherlist = NULL; - zval **val; + zval *val; if (sslsock->ssl_handle) { if (sslsock->s.is_blocked) { @@ -1444,7 +1418,7 @@ int php_openssl_setup_crypto(php_stream *stream, } #if OPENSSL_VERSION_NUMBER >= 0x0090806fL - if (GET_VER_OPT("no_ticket") && zend_is_true(*val TSRMLS_CC)) { + if (GET_VER_OPT("no_ticket") && zend_is_true(val TSRMLS_CC)) { ssl_ctx_options |= SSL_OP_NO_TICKET; } #endif @@ -1454,12 +1428,12 @@ int php_openssl_setup_crypto(php_stream *stream, #endif #if OPENSSL_VERSION_NUMBER >= 0x10000000L - if (!GET_VER_OPT("disable_compression") || zend_is_true(*val TSRMLS_CC)) { + if (!GET_VER_OPT("disable_compression") || zend_is_true(val TSRMLS_CC)) { ssl_ctx_options |= SSL_OP_NO_COMPRESSION; } #endif - if (GET_VER_OPT("verify_peer") && !zend_is_true(*val TSRMLS_CC)) { + if (GET_VER_OPT("verify_peer") && !zend_is_true(val TSRMLS_CC)) { disable_peer_verification(sslsock->ctx, stream TSRMLS_CC); } else if (FAILURE == enable_peer_verification(sslsock->ctx, stream TSRMLS_CC)) { return FAILURE; @@ -1486,7 +1460,7 @@ int php_openssl_setup_crypto(php_stream *stream, SSL_CTX_set_options(sslsock->ctx, ssl_ctx_options); if (sslsock->is_client == 0 && - stream->context && + PHP_STREAM_CONTEXT(stream) && FAILURE == set_server_specific_opts(stream, sslsock->ctx TSRMLS_CC) ) { return FAILURE; @@ -1539,9 +1513,9 @@ int php_openssl_setup_crypto(php_stream *stream, } /* }}} */ -static zval *capture_session_meta(SSL *ssl_handle) /* {{{ */ +static zend_array *capture_session_meta(SSL *ssl_handle) /* {{{ */ { - zval *meta_arr; + zval meta_arr; char *proto_str; long proto = SSL_version(ssl_handle); const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_handle); @@ -1557,61 +1531,55 @@ static zval *capture_session_meta(SSL *ssl_handle) /* {{{ */ default: proto_str = "UNKNOWN"; } - MAKE_STD_ZVAL(meta_arr); - array_init(meta_arr); - add_assoc_string(meta_arr, "protocol", proto_str, 1); - add_assoc_string(meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher), 1); - add_assoc_long(meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL)); - add_assoc_string(meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher), 1); + array_init(&meta_arr); + add_assoc_string(&meta_arr, "protocol", proto_str); + add_assoc_string(&meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher)); + add_assoc_long(&meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL)); + add_assoc_string(&meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher)); - return meta_arr; + return Z_ARR(meta_arr); } /* }}} */ static int capture_peer_certs(php_stream *stream, php_openssl_netstream_data_t *sslsock, X509 *peer_cert TSRMLS_DC) /* {{{ */ { - zval **val, *zcert; + zval *val, zcert; int cert_captured = 0; - if (SUCCESS == php_stream_context_get_option(stream->context, - "ssl", "capture_peer_cert", &val) && - zend_is_true(*val TSRMLS_CC) + if (NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), + "ssl", "capture_peer_cert")) && + zend_is_true(val TSRMLS_CC) ) { - MAKE_STD_ZVAL(zcert); - ZVAL_RESOURCE(zcert, zend_list_insert(peer_cert, php_openssl_get_x509_list_id() TSRMLS_CC)); - php_stream_context_set_option(stream->context, "ssl", "peer_certificate", zcert); + zend_register_resource(&zcert, peer_cert, php_openssl_get_x509_list_id() TSRMLS_CC); + php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_certificate", &zcert); cert_captured = 1; - FREE_ZVAL(zcert); } - if (SUCCESS == php_stream_context_get_option(stream->context, - "ssl", "capture_peer_cert_chain", &val) && - zend_is_true(*val TSRMLS_CC) + if (NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), + "ssl", "capture_peer_cert_chain")) && + zend_is_true(val TSRMLS_CC) ) { - zval *arr; + zval arr; STACK_OF(X509) *chain; - MAKE_STD_ZVAL(arr); chain = SSL_get_peer_cert_chain(sslsock->ssl_handle); if (chain && sk_X509_num(chain) > 0) { int i; - array_init(arr); + array_init(&arr); for (i = 0; i < sk_X509_num(chain); i++) { X509 *mycert = X509_dup(sk_X509_value(chain, i)); - MAKE_STD_ZVAL(zcert); - ZVAL_RESOURCE(zcert, zend_list_insert(mycert, php_openssl_get_x509_list_id() TSRMLS_CC)); - add_next_index_zval(arr, zcert); + zend_register_resource(&zcert, mycert, php_openssl_get_x509_list_id() TSRMLS_CC); + add_next_index_zval(&arr, &zcert); } } else { - ZVAL_NULL(arr); + ZVAL_NULL(&arr); } - php_stream_context_set_option(stream->context, "ssl", "peer_certificate_chain", arr); - zval_dtor(arr); - efree(arr); + php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_certificate_chain", &arr); + zval_dtor(&arr); } return cert_captured; @@ -1718,7 +1686,7 @@ static int php_openssl_enable_crypto(php_stream *stream, if (n == 1) { peer_cert = SSL_get_peer_certificate(sslsock->ssl_handle); - if (peer_cert && stream->context) { + if (peer_cert && PHP_STREAM_CONTEXT(stream)) { cert_captured = capture_peer_certs(stream, sslsock, peer_cert TSRMLS_CC); } @@ -1728,17 +1696,17 @@ static int php_openssl_enable_crypto(php_stream *stream, } else { sslsock->ssl_active = 1; - if (stream->context) { - zval **val; + if (PHP_STREAM_CONTEXT(stream)) { + zval *val; - if (SUCCESS == php_stream_context_get_option(stream->context, - "ssl", "capture_session_meta", &val) && - zend_is_true(*val TSRMLS_CC) + if (NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), + "ssl", "capture_session_meta")) && + zend_is_true(val TSRMLS_CC) ) { - zval *meta_arr = capture_session_meta(sslsock->ssl_handle); - php_stream_context_set_option(stream->context, "ssl", "session_meta", meta_arr); - zval_dtor(meta_arr); - efree(meta_arr); + zval meta_arr; + ZVAL_ARR(&meta_arr, capture_session_meta(sslsock->ssl_handle)); + php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "session_meta", &meta_arr); + zval_dtor(&meta_arr); } } } @@ -1747,7 +1715,7 @@ static int php_openssl_enable_crypto(php_stream *stream, } else { n = -1; peer_cert = SSL_get_peer_certificate(sslsock->ssl_handle); - if (peer_cert && stream->context) { + if (peer_cert && PHP_STREAM_CONTEXT(stream)) { cert_captured = capture_peer_certs(stream, sslsock, peer_cert TSRMLS_CC); } } @@ -1786,7 +1754,7 @@ static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size } while(retry); if (didwrite > 0) { - php_stream_notify_progress_increment(stream->context, didwrite, 0); + php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), didwrite, 0); } } else { didwrite = php_stream_socket_ops.write(stream, buf, count TSRMLS_CC); @@ -1874,7 +1842,7 @@ static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t coun } while (retry); if (nr_bytes > 0) { - php_stream_notify_progress_increment(stream->context, nr_bytes, 0); + php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), nr_bytes, 0); } } else @@ -1979,7 +1947,6 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ clisock = php_network_accept_incoming(sock->s.socket, xparam->want_textaddr ? &xparam->outputs.textaddr : NULL, - xparam->want_textaddr ? &xparam->outputs.textaddrlen : NULL, xparam->want_addr ? &xparam->outputs.addr : NULL, xparam->want_addr ? &xparam->outputs.addrlen : NULL, xparam->inputs.timeout, @@ -2004,9 +1971,9 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ xparam->outputs.client = php_stream_alloc_rel(stream->ops, clisockdata, NULL, "r+"); if (xparam->outputs.client) { - xparam->outputs.client->context = stream->context; - if (stream->context) { - zend_list_addref(stream->context->rsrc_id); + xparam->outputs.client->ctx = stream->ctx; + if (stream->ctx) { + GC_REFCOUNT(stream->ctx)++; } } } @@ -2202,11 +2169,11 @@ php_stream_ops php_openssl_socket_ops = { static long get_crypto_method(php_stream_context *ctx, long crypto_method) { - zval **val; + zval *val; - if (ctx && php_stream_context_get_option(ctx, "ssl", "crypto_method", &val) == SUCCESS) { + if (ctx && (val = php_stream_context_get_option(ctx, "ssl", "crypto_method")) != NULL) { convert_to_long_ex(val); - crypto_method = (long)Z_LVAL_PP(val); + crypto_method = (long)Z_LVAL_P(val); crypto_method |= STREAM_CRYPTO_IS_CLIENT; } |