mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix GH-11054: Reset OpenSSL errors when using a PEM public key
The error happens when the PEM contains a public key, as it will be first tried to be parsed as a certificate. The parsing as a certificate fails, which then leads to a corresponding error tracked by PHP with the next call to php_openssl_store_errors(). This change introduces an error marking to be able to reset the stored errors to the state before trying the certificate. Closes GH-11055
This commit is contained in:
committed by
Jakub Zelenka
parent
5690e8baea
commit
4d4b9604ca
2
NEWS
2
NEWS
@@ -118,6 +118,8 @@ PHP NEWS
|
||||
- OpenSSL:
|
||||
. Added OPENSSL_CMS_OLDMIMETYPE and PKCS7_NOOLDMIMETYPE contants to switch
|
||||
between mime content types. (Daniel Kesselberg)
|
||||
. Fixed GH-11054: Reset OpenSSL errors when using a PEM public key.
|
||||
(Florian Moser)
|
||||
|
||||
- PCNTL:
|
||||
. SA_ONSTACK is now set for pcntl_signal. (Kévin Dunglas)
|
||||
|
||||
@@ -476,6 +476,37 @@ void php_openssl_store_errors(void)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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, ...)
|
||||
{
|
||||
@@ -1293,6 +1324,7 @@ PHP_GINIT_FUNCTION(openssl)
|
||||
ZEND_TSRMLS_CACHE_UPDATE();
|
||||
#endif
|
||||
openssl_globals->errors = NULL;
|
||||
openssl_globals->errors_mark = NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -1302,6 +1334,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);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -3571,12 +3606,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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
9
ext/openssl/tests/bug11054.pem
Normal file
9
ext/openssl/tests/bug11054.pem
Normal file
@@ -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-----
|
||||
15
ext/openssl/tests/bug11054.phpt
Normal file
15
ext/openssl/tests/bug11054.phpt
Normal file
@@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
Bug #11054: Calling with a PEM public key results in error
|
||||
--EXTENSIONS--
|
||||
openssl
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$key_file_name = __DIR__ . '/bug11054.pem';
|
||||
$key_content = file_get_contents($key_file_name);
|
||||
openssl_get_publickey($key_content);
|
||||
var_dump(openssl_error_string());
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(false)
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user