Commit 4d544e43c44 for php.net

commit 4d544e43c4429f5a17c4cdad75613686eac260ff
Merge: 1c941755f8a 4a16d22970b
Author: ndossche <7771979+ndossche@users.noreply.github.com>
Date:   Fri Apr 3 22:43:53 2026 +0200

    Merge branch 'PHP-8.4' into PHP-8.5

    * PHP-8.4:
      openssl: Fix error propagation in csr exports (#21403)
      openssl: Fix missing error propagation in openssl_x509_export() (#21375)
      Fix SKIPIF of openssl_password.phpt (#20941)

diff --cc ext/openssl/openssl.c
index ad2457672d0,22f25a48eed..f33e3bcf299
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@@ -1573,52 -2920,274 +1572,52 @@@ cleanup

  /* {{{ x509 CSR functions */

 -static zend_result php_openssl_csr_add_subj_entry(zval *item, X509_NAME *subj, int nid)
 +/* {{{ Exports a CSR to file */
 +PHP_FUNCTION(openssl_csr_export_to_file)
  {
 -	zend_string *str_item = zval_try_get_string(item);
 -	if (UNEXPECTED(!str_item)) {
 -		return FAILURE;
 -	}
 -	if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8,
 -				(unsigned char*)ZSTR_VAL(str_item), -1, -1, 0))
 -	{
 -		php_openssl_store_errors();
 -		php_error_docref(NULL, E_WARNING,
 -			"dn: add_entry_by_NID %d -> %s (failed; check error"
 -			" queue and value of string_mask OpenSSL option "
 -			"if illegal characters are reported)",
 -			nid, ZSTR_VAL(str_item));
 -		zend_string_release(str_item);
 -		return FAILURE;
 -	}
 -	zend_string_release(str_item);
 -	return SUCCESS;
 -}
 +	X509_REQ *csr;
 +	zend_object *csr_obj;
 +	zend_string *csr_str;
 +	bool notext = 1;
 +	char * filename = NULL;
 +	size_t filename_len;
 +	char file_path[MAXPATHLEN];
 +	BIO * bio_out;

 -static zend_result php_openssl_csr_make(struct php_x509_request * req, X509_REQ * csr, zval * dn, zval * attribs)
 -{
 -	STACK_OF(CONF_VALUE) * dn_sk, *attr_sk = NULL;
 -	char * str, *dn_sect, *attr_sect;
 +	ZEND_PARSE_PARAMETERS_START(2, 3)
 +		Z_PARAM_OBJ_OF_CLASS_OR_STR(csr_obj, php_openssl_request_ce, csr_str)
 +		Z_PARAM_PATH(filename, filename_len)
 +		Z_PARAM_OPTIONAL
 +		Z_PARAM_BOOL(notext)
 +	ZEND_PARSE_PARAMETERS_END();

 -	dn_sect = NCONF_get_string(req->req_config, req->section_name, "distinguished_name");
 -	if (dn_sect == NULL) {
 -		php_openssl_store_errors();
 -		return FAILURE;
 +	RETVAL_FALSE;
 +
 +	csr = php_openssl_csr_from_param(csr_obj, csr_str, 1);
 +	if (csr == NULL) {
 +		php_error_docref(NULL, E_WARNING, "X.509 Certificate Signing Request cannot be retrieved");
 +		return;
  	}
 -	dn_sk = NCONF_get_section(req->req_config, dn_sect);
 -	if (dn_sk == NULL) {
 -		php_openssl_store_errors();
 -		return FAILURE;
 +
 +	if (!php_openssl_check_path(filename, filename_len, file_path, 2)) {
 +		goto exit_cleanup;
  	}
 -	attr_sect = php_openssl_conf_get_string(req->req_config, req->section_name, "attributes");
 -	if (attr_sect == NULL) {
 -		attr_sk = NULL;
 -	} else {
 -		attr_sk = NCONF_get_section(req->req_config, attr_sect);
 -		if (attr_sk == NULL) {
 +
 +	bio_out = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY));
 +	if (bio_out != NULL) {
 +		if (!notext && !X509_REQ_print(bio_out, csr)) {
++			/* TODO: warn? */
  			php_openssl_store_errors();
- 		}
- 		if (!PEM_write_bio_X509_REQ(bio_out, csr)) {
 -			return FAILURE;
++		} else if (!PEM_write_bio_X509_REQ(bio_out, csr)) {
 +			php_error_docref(NULL, E_WARNING, "Error writing PEM to file %s", file_path);
 +			php_openssl_store_errors();
 +		} else {
 +			RETVAL_TRUE;
  		}
 -	}
 -	/* setup the version number: version 1 */
 -	if (X509_REQ_set_version(csr, 0L)) {
 -		int i, nid;
 -		char *type;
 -		CONF_VALUE *v;
 -		X509_NAME *subj;
 -		zval *item, *subitem;
 -		zend_string *strindex = NULL;
 -
 -		subj = X509_REQ_get_subject_name(csr);
 -		/* apply values from the dn hash */
 -		ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(dn), strindex, item) {
 -			if (strindex) {
 -				int nid = OBJ_txt2nid(ZSTR_VAL(strindex));
 -				if (nid != NID_undef) {
 -					if (Z_TYPE_P(item) == IS_ARRAY) {
 -						ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(item), i, subitem) {
 -							if (php_openssl_csr_add_subj_entry(subitem, subj, nid) == FAILURE) {
 -								return FAILURE;
 -							}
 -						} ZEND_HASH_FOREACH_END();
 -					} else if (php_openssl_csr_add_subj_entry(item, subj, nid) == FAILURE) {
 -						return FAILURE;
 -					}
 -				} else {
 -					php_error_docref(NULL, E_WARNING, "dn: %s is not a recognized name", ZSTR_VAL(strindex));
 -				}
 -			}
 -		} ZEND_HASH_FOREACH_END();
 -
 -		/* Finally apply defaults from config file */
 -		for(i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
 -			size_t len;
 -			char buffer[200 + 1]; /*200 + \0 !*/
 -
 -			v = sk_CONF_VALUE_value(dn_sk, i);
 -			type = v->name;
 -
 -			len = strlen(type);
 -			if (len < sizeof("_default")) {
 -				continue;
 -			}
 -			len -= sizeof("_default") - 1;
 -			if (strcmp("_default", type + len) != 0) {
 -				continue;
 -			}
 -			if (len > 200) {
 -				len = 200;
 -			}
 -			memcpy(buffer, type, len);
 -			buffer[len] = '\0';
 -			type = buffer;
 -
 -			/* Skip past any leading X. X: X, etc to allow for multiple
 -			 * instances */
 -			for (str = type; *str; str++) {
 -				if (*str == ':' || *str == ',' || *str == '.') {
 -					str++;
 -					if (*str) {
 -						type = str;
 -					}
 -					break;
 -				}
 -			}
 -			/* if it is already set, skip this */
 -			nid = OBJ_txt2nid(type);
 -			if (X509_NAME_get_index_by_NID(subj, nid, -1) >= 0) {
 -				continue;
 -			}
 -			if (!X509_NAME_add_entry_by_txt(subj, type, MBSTRING_UTF8, (unsigned char*)v->value, -1, -1, 0)) {
 -				php_openssl_store_errors();
 -				php_error_docref(NULL, E_WARNING, "add_entry_by_txt %s -> %s (failed)", type, v->value);
 -				return FAILURE;
 -			}
 -			if (!X509_NAME_entry_count(subj)) {
 -				php_error_docref(NULL, E_WARNING, "No objects specified in config file");
 -				return FAILURE;
 -			}
 -		}
 -		if (attribs) {
 -			ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(attribs), strindex, item) {
 -				int nid;
 -
 -				if (NULL == strindex) {
 -					php_error_docref(NULL, E_WARNING, "attributes: numeric fild names are not supported");
 -					continue;
 -				}
 -
 -				nid = OBJ_txt2nid(ZSTR_VAL(strindex));
 -				if (nid != NID_undef) {
 -					zend_string *str_item = zval_try_get_string(item);
 -					if (UNEXPECTED(!str_item)) {
 -						return FAILURE;
 -					}
 -					if (!X509_REQ_add1_attr_by_NID(csr, nid, MBSTRING_UTF8, (unsigned char*)ZSTR_VAL(str_item), (int)ZSTR_LEN(str_item))) {
 -						php_openssl_store_errors();
 -						php_error_docref(NULL, E_WARNING, "attributes: add_attr_by_NID %d -> %s (failed)", nid, ZSTR_VAL(str_item));
 -						zend_string_release(str_item);
 -						return FAILURE;
 -					}
 -					zend_string_release(str_item);
 -				} else {
 -					php_error_docref(NULL, E_WARNING, "attributes: %s is not a recognized attribute name", ZSTR_VAL(strindex));
 -				}
 -			} ZEND_HASH_FOREACH_END();
 -			for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
 -				v = sk_CONF_VALUE_value(attr_sk, i);
 -				/* if it is already set, skip this */
 -				nid = OBJ_txt2nid(v->name);
 -				if (X509_REQ_get_attr_by_NID(csr, nid, -1) >= 0) {
 -					continue;
 -				}
 -				if (!X509_REQ_add1_attr_by_txt(csr, v->name, MBSTRING_UTF8, (unsigned char*)v->value, -1)) {
 -					php_openssl_store_errors();
 -					php_error_docref(NULL, E_WARNING,
 -						"add1_attr_by_txt %s -> %s (failed; check error queue "
 -						"and value of string_mask OpenSSL option if illegal "
 -						"characters are reported)",
 -						v->name, v->value);
 -					return FAILURE;
 -				}
 -			}
 -		}
 -	} else {
 -		php_openssl_store_errors();
 -	}
 -
 -	if (!X509_REQ_set_pubkey(csr, req->priv_key)) {
 -		php_openssl_store_errors();
 -	}
 -	return SUCCESS;
 -}
 -
 -static X509_REQ *php_openssl_csr_from_str(zend_string *csr_str, uint32_t arg_num)
 -{
 -	X509_REQ * csr = NULL;
 -	char file_path[MAXPATHLEN];
 -	BIO * in;
 -
 -	if (ZSTR_LEN(csr_str) > 7 && memcmp(ZSTR_VAL(csr_str), "file://", sizeof("file://") - 1) == 0) {
 -		if (!php_openssl_check_path_str(csr_str, file_path, arg_num)) {
 -			return NULL;
 -		}
 -		in = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
 -	} else {
 -		in = BIO_new_mem_buf(ZSTR_VAL(csr_str), (int) ZSTR_LEN(csr_str));
 -	}
 -
 -	if (in == NULL) {
 -		php_openssl_store_errors();
 -		return NULL;
 -	}
 -
 -	csr = PEM_read_bio_X509_REQ(in, NULL,NULL,NULL);
 -	if (csr == NULL) {
 -		php_openssl_store_errors();
 -	}
 -
 -	BIO_free(in);
 -
 -	return csr;
 -}
 -
 -static X509_REQ *php_openssl_csr_from_param(
 -		zend_object *csr_obj, zend_string *csr_str, uint32_t arg_num)
 -{
 -	if (csr_obj) {
 -		return php_openssl_request_from_obj(csr_obj)->csr;
 -	}
 -
 -	ZEND_ASSERT(csr_str);
 -
 -	return php_openssl_csr_from_str(csr_str, arg_num);
 -}
 -
 -/* {{{ Exports a CSR to file */
 -PHP_FUNCTION(openssl_csr_export_to_file)
 -{
 -	X509_REQ *csr;
 -	zend_object *csr_obj;
 -	zend_string *csr_str;
 -	bool notext = 1;
 -	char * filename = NULL;
 -	size_t filename_len;
 -	char file_path[MAXPATHLEN];
 -	BIO * bio_out;
 -
 -	ZEND_PARSE_PARAMETERS_START(2, 3)
 -		Z_PARAM_OBJ_OF_CLASS_OR_STR(csr_obj, php_openssl_request_ce, csr_str)
 -		Z_PARAM_PATH(filename, filename_len)
 -		Z_PARAM_OPTIONAL
 -		Z_PARAM_BOOL(notext)
 -	ZEND_PARSE_PARAMETERS_END();
 -
 -	RETVAL_FALSE;
 -
 -	csr = php_openssl_csr_from_param(csr_obj, csr_str, 1);
 -	if (csr == NULL) {
 -		php_error_docref(NULL, E_WARNING, "X.509 Certificate Signing Request cannot be retrieved");
 -		return;
 -	}
 -
 -	if (!php_openssl_check_path(filename, filename_len, file_path, 2)) {
 -		goto exit_cleanup;
 -	}
 -
 -	bio_out = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY));
 -	if (bio_out != NULL) {
 -		if (!notext && !X509_REQ_print(bio_out, csr)) {
 -			/* TODO: warn? */
 -			php_openssl_store_errors();
 -		} else if (!PEM_write_bio_X509_REQ(bio_out, csr)) {
 -			php_error_docref(NULL, E_WARNING, "Error writing PEM to file %s", file_path);
 -			php_openssl_store_errors();
 -		} else {
 -			RETVAL_TRUE;
 -		}
 -		BIO_free(bio_out);
 -	} else {
 -		php_openssl_store_errors();
 -		php_error_docref(NULL, E_WARNING, "Error opening file %s", file_path);
 +		BIO_free(bio_out);
 +	} else {
 +		php_openssl_store_errors();
 +		php_error_docref(NULL, E_WARNING, "Error opening file %s", file_path);
  	}

  exit_cleanup: