Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion ext/openssl/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,12 @@ PHP_METHOD(Openssl_Session, __unserialize)
Z_PARAM_ARRAY_HT(data)
ZEND_PARSE_PARAMETERS_END();

php_openssl_session_object *obj = Z_OPENSSL_SESSION_P(ZEND_THIS);
if (obj->session != NULL) {
zend_throw_error(NULL, "Cannot call Openssl\\Session::__unserialize() on an already-initialized session");
RETURN_THROWS();
}

zval *pem_zv = zend_hash_str_find(data, ZEND_STRL("pem"));
if (!pem_zv || Z_TYPE_P(pem_zv) != IS_STRING) {
zend_throw_exception(php_openssl_exception_ce, "Invalid serialization data", 0);
Expand All @@ -455,7 +461,6 @@ PHP_METHOD(Openssl_Session, __unserialize)
RETURN_THROWS();
}

php_openssl_session_object *obj = Z_OPENSSL_SESSION_P(ZEND_THIS);
obj->session = session;

/* Populate id property */
Expand Down
84 changes: 84 additions & 0 deletions ext/openssl/tests/session_unserialize_repeat.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
--TEST--
Openssl\Session::__unserialize throws on a repeat call
--EXTENSIONS--
openssl
--SKIPIF--
<?php
if (!function_exists("proc_open")) die("skip no proc_open");
?>
--FILE--
<?php
$certFile = __DIR__ . DIRECTORY_SEPARATOR . 'session_unserialize_repeat.pem.tmp';

$serverCode = <<<'CODE'
$serverCtx = stream_context_create(['ssl' => [
'local_cert' => '%s',
]]);

$server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr,
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $serverCtx);
phpt_notify_server_start($server);

$client = @stream_socket_accept($server, 10);
if ($client) {
fwrite($client, "ok\n");
fclose($client);
}
CODE;
$serverCode = sprintf($serverCode, $certFile);

$clientCode = <<<'CODE'
$captured = null;
$ctx = stream_context_create(['ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'session_new_cb' => function ($s, $session) use (&$captured) {
$captured = $session;
return true;
},
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
]]);

$c = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 10,
STREAM_CLIENT_CONNECT, $ctx);
if (!$c) {
echo "connect failed: $errstr\n";
return;
}
fread($c, 8);
fclose($c);

if (!$captured instanceof Openssl\Session) {
echo "no session captured\n";
return;
}

$payload = $captured->__serialize();
$sess = unserialize(serialize($captured));
echo "first: " . (is_object($sess) ? get_class($sess) : "fail") . "\n";

try {
$sess->__unserialize($payload);
echo "second: no throw\n";
} catch (Error $e) {
echo "second: " . $e->getMessage() . "\n";
}

echo "alive\n";
CODE;

include 'CertificateGenerator.inc';
$certificateGenerator = new CertificateGenerator();
$certificateGenerator->saveNewCertAsFileWithKey('session-unserialize-repeat', $certFile);

include 'ServerClientTestCase.inc';
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
?>
--CLEAN--
<?php
@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'session_unserialize_repeat.pem.tmp');
?>
--EXPECTF--
first: Openssl\Session
second: Cannot call Openssl\Session::__unserialize() on an already-initialized session
alive
Loading