diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 10af453c89519..83501f5e907f6 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -474,6 +474,37 @@ void php_openssl_store_errors() } /* }}} */ +/* {{{ php_openssl_errors_set_mark */ +void php_openssl_errors_set_mark(void) { + if (!OPENSSL_G(errors)) { + return; + } + + if (!OPENSSL_G(errors_mark)) { + OPENSSL_G(errors_mark) = pecalloc(1, sizeof(struct php_openssl_errors), 1); + } + + memcpy(OPENSSL_G(errors_mark), OPENSSL_G(errors), sizeof(struct php_openssl_errors)); +} +/* }}} */ + +/* {{{ php_openssl_errors_restore_mark */ +void php_openssl_errors_restore_mark(void) { + if (!OPENSSL_G(errors)) { + return; + } + + struct php_openssl_errors *errors = OPENSSL_G(errors); + + if (!OPENSSL_G(errors_mark)) { + errors->top = 0; + errors->bottom = 0; + } else { + memcpy(errors, OPENSSL_G(errors_mark), sizeof(struct php_openssl_errors)); + } +} +/* }}} */ + /* openssl file path check error function */ static void php_openssl_check_path_error(uint32_t arg_num, int type, const char *format, ...) { @@ -1415,6 +1446,7 @@ PHP_GINIT_FUNCTION(openssl) ZEND_TSRMLS_CACHE_UPDATE(); #endif openssl_globals->errors = NULL; + openssl_globals->errors_mark = NULL; } /* }}} */ @@ -1424,6 +1456,9 @@ PHP_GSHUTDOWN_FUNCTION(openssl) if (openssl_globals->errors) { pefree(openssl_globals->errors, 1); } + if (openssl_globals->errors_mark) { + pefree(openssl_globals->errors_mark, 1); + } } /* }}} */ @@ -3690,12 +3725,14 @@ static EVP_PKEY *php_openssl_pkey_from_zval( } /* it's an X509 file/cert of some kind, and we need to extract the data from that */ if (public_key) { + php_openssl_errors_set_mark(); cert = php_openssl_x509_from_str(Z_STR_P(val), arg_num, false, NULL); if (cert) { free_cert = 1; } else { /* not a X509 certificate, try to retrieve public key */ + php_openssl_errors_restore_mark(); BIO* in; if (is_file) { in = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY)); diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index 3f0c436190fa3..66f76f6ace546 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -80,6 +80,7 @@ struct php_openssl_errors { ZEND_BEGIN_MODULE_GLOBALS(openssl) struct php_openssl_errors *errors; + struct php_openssl_errors *errors_mark; ZEND_END_MODULE_GLOBALS(openssl) #define OPENSSL_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(openssl, v) diff --git a/ext/openssl/tests/bug11054.pem b/ext/openssl/tests/bug11054.pem new file mode 100644 index 0000000000000..60d7afa827f2c --- /dev/null +++ b/ext/openssl/tests/bug11054.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvYH14fT4DPgyffkDOrHt +x0q+rxclB48h2ykgbR3QyDG2d7hMSXjtqEseO/iR1FdAv7UevIKyHFbHpJilOIwo +mEqQNxUQCWdZsWhv7ZVfG8UUgki7LKMGPruJM97vteBS101hSCaCQz+zTyVyP8Uy +nqx5zlPmcBUA92gAFfSCa+tm/lR2BY5g/20mZX/lMY0xXV1iLhfdK6RgJYXX2SdH +YR/01IgmjgTfIp7gX+xixDgGZuZY++jo8C52udFkCf5vxyG4Ed57vRfCLFOPfeY4 +r3i0Jiply65zSo8y/6KxudRtmGOfV2qb2EsMTW9PaLs3+rnhhiYBM/nR4V5ux6u6 +DwIDAQAB +-----END PUBLIC KEY----- diff --git a/ext/openssl/tests/bug11054.phpt b/ext/openssl/tests/bug11054.phpt new file mode 100644 index 0000000000000..25f23d5b1de3e --- /dev/null +++ b/ext/openssl/tests/bug11054.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #11054: Calling with a PEM public key results in error +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECT-- +bool(false) diff --git a/ext/openssl/tests/openssl_error_string_basic.phpt b/ext/openssl/tests/openssl_error_string_basic.phpt index e4ea264b3bf1f..02e8b3fbc49d1 100644 --- a/ext/openssl/tests/openssl_error_string_basic.phpt +++ b/ext/openssl/tests/openssl_error_string_basic.phpt @@ -123,7 +123,7 @@ expect_openssl_errors('openssl_private_decrypt', ['04065072']); // public encrypt and decrypt with failed padding check and padding @openssl_public_encrypt("data", $crypted, $public_key_file, 1000); @openssl_public_decrypt("data", $crypted, $public_key_file); -expect_openssl_errors('openssl_private_(en|de)crypt padding', [$err_pem_no_start_line, '0408F090', '04067072']); +expect_openssl_errors('openssl_private_(en|de)crypt padding', ['0408F090', '04067072']); // X509 echo "X509 errors\n"; diff --git a/ext/openssl/tests/openssl_error_string_basic_openssl3.phpt b/ext/openssl/tests/openssl_error_string_basic_openssl3.phpt index d435a53e3047f..041a0a0b5648a 100644 --- a/ext/openssl/tests/openssl_error_string_basic_openssl3.phpt +++ b/ext/openssl/tests/openssl_error_string_basic_openssl3.phpt @@ -114,9 +114,6 @@ expect_openssl_errors('openssl_pkey_export_to_file write', ['10080002']); // successful export @openssl_pkey_export($private_key_file_with_pass, $out, 'wrong pwd', $options); expect_openssl_errors('openssl_pkey_export', ['1C800064', '04800065']); -// invalid x509 for getting public key -@openssl_pkey_get_public($private_key_file); -expect_openssl_errors('openssl_pkey_get_public', [$err_pem_no_start_line]); // private encrypt with unknown padding @openssl_private_encrypt("data", $crypted, $private_key_file, 1000); expect_openssl_errors('openssl_private_encrypt', ['1C8000A5']); @@ -126,7 +123,7 @@ expect_openssl_errors('openssl_private_decrypt', ['0200009F', '02000072']); // public encrypt and decrypt with failed padding check and padding @openssl_public_encrypt("data", $crypted, $public_key_file, 1000); @openssl_public_decrypt("data", $crypted, $public_key_file); -expect_openssl_errors('openssl_private_(en|de)crypt padding', [$err_pem_no_start_line, '02000076', '0200008A', '02000072', '1C880004']); +expect_openssl_errors('openssl_private_(en|de)crypt padding', ['02000076', '0200008A', '02000072', '1C880004']); // X509 echo "X509 errors\n"; @@ -170,7 +167,6 @@ openssl_pkey_export_to_file opening: ok openssl_pkey_export_to_file pem: ok openssl_pkey_export_to_file write: ok openssl_pkey_export: ok -openssl_pkey_get_public: ok openssl_private_encrypt: ok openssl_private_decrypt: ok openssl_private_(en|de)crypt padding: ok