BUG_73819: call ssh2_shell() causes segment fault

1. php_ssh2_shell_open() was calling zend_hash_get_current_key_ex
2. php_ssh2_exec_command() / php_ssh2_shell_open() / php_ssh2_direct_tcpip()
   were being passed a pointer instead of the resource ID.
3. Renamed session_rsrc to session_rsrcid
3. Added test for ssh2_shell and reading / writing to the stream
This commit is contained in:
Mitch Hagstrand
2017-02-05 22:06:27 -08:00
committed by Casper Langemeijer
parent 756e2f1369
commit 62d00b340f
4 changed files with 40 additions and 16 deletions

View File

@@ -118,8 +118,8 @@ typedef struct _php_ssh2_channel_data {
char is_blocking;
long timeout;
/* Resource ID, zend_list_addref() when opening, zend_list_delete() when closing */
long session_rsrc;
/* Resource ID */
int session_rsrcid;
/* Allow one stream to be closed while the other is kept open */
unsigned char *refcount;

6
ssh2.c
View File

@@ -810,7 +810,7 @@ PHP_FUNCTION(ssh2_forward_accept)
channel_data->channel = channel;
channel_data->streamid = 0;
channel_data->is_blocking = 0;
channel_data->session_rsrc = data->session_rsrcid;
channel_data->session_rsrcid = data->session_rsrcid;
channel_data->refcount = NULL;
stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
@@ -821,7 +821,7 @@ PHP_FUNCTION(ssh2_forward_accept)
RETURN_FALSE;
}
//TODO Sean-Der
//zend_list_addref(channel_data->session_rsrc);
//zend_list_addref(channel_data->session_rsrcid);
php_stream_to_zval(stream, return_value);
}
@@ -975,7 +975,7 @@ PHP_FUNCTION(ssh2_publickey_init)
data = emalloc(sizeof(php_ssh2_pkey_subsys_data));
data->session = session;
data->session_rsrcid = Z_LVAL_P(zsession);
data->session_rsrcid = Z_RES_P(zsession)->handle;
//TODO Sean-Der
//zend_list_addref(data->session_rsrcid);
data->pkey = pkey;

View File

@@ -50,7 +50,7 @@ static size_t php_ssh2_channel_stream_write(php_stream *stream, const char *buf,
zval *zresource;
libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking);
zresource = php_ssh2_zval_from_resource_handle(abstract->session_rsrc);
zresource = php_ssh2_zval_from_resource_handle(abstract->session_rsrcid);
session = (LIBSSH2_SESSION *)zend_fetch_resource(Z_RES_P(zresource), PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
@@ -94,7 +94,7 @@ static size_t php_ssh2_channel_stream_read(php_stream *stream, char *buf, size_t
stream->eof = libssh2_channel_eof(abstract->channel);
libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking);
zresource = php_ssh2_zval_from_resource_handle(abstract->session_rsrc);
zresource = php_ssh2_zval_from_resource_handle(abstract->session_rsrcid);
session = (LIBSSH2_SESSION *)zend_fetch_resource(Z_RES_P(zresource), PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
#ifdef PHP_SSH2_SESSION_TIMEOUT
@@ -138,7 +138,7 @@ static int php_ssh2_channel_stream_close(php_stream *stream, int close_handle)
libssh2_channel_eof(abstract->channel);
libssh2_channel_free(abstract->channel);
//TODO Sean-Der
//zend_list_delete(abstract->session_rsrc);
//zend_list_delete(abstract->session_rsrcid);
}
efree(abstract);
@@ -516,7 +516,7 @@ static php_stream *php_ssh2_shell_open(LIBSSH2_SESSION *session, int resource_id
zend_ulong idx;
for(zend_hash_internal_pointer_reset(HASH_OF(environment));
(key_type = zend_hash_get_current_key_ex(HASH_OF(environment), &key, &idx, NULL)) != HASH_KEY_NON_EXISTENT;
(key_type = zend_hash_get_current_key(HASH_OF(environment), &key, &idx)) != HASH_KEY_NON_EXISTENT;
zend_hash_move_forward(HASH_OF(environment))) {
if (key_type == HASH_KEY_IS_STRING) {
zval *value;
@@ -563,7 +563,7 @@ static php_stream *php_ssh2_shell_open(LIBSSH2_SESSION *session, int resource_id
channel_data->streamid = 0;
channel_data->is_blocking = 0;
channel_data->timeout = 0;
channel_data->session_rsrc = resource_id;
channel_data->session_rsrcid = resource_id;
channel_data->refcount = NULL;
stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
@@ -715,7 +715,7 @@ PHP_FUNCTION(ssh2_shell)
SSH2_FETCH_AUTHENTICATED_SESSION(session, zsession);
stream = php_ssh2_shell_open(session, Z_LVAL_P(zsession), term, term_len, environment, width, height, type);
stream = php_ssh2_shell_open(session, Z_RES_P(zsession)->handle, term, term_len, environment, width, height, type);
if (!stream) {
RETURN_FALSE;
}
@@ -804,7 +804,7 @@ static php_stream *php_ssh2_exec_command(LIBSSH2_SESSION *session, int resource_
channel_data->streamid = 0;
channel_data->is_blocking = 0;
channel_data->timeout = 0;
channel_data->session_rsrc = resource_id;
channel_data->session_rsrcid = resource_id;
channel_data->refcount = NULL;
stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
@@ -948,7 +948,7 @@ PHP_FUNCTION(ssh2_exec)
SSH2_FETCH_AUTHENTICATED_SESSION(session, zsession);
stream = php_ssh2_exec_command(session, Z_LVAL_P(zsession), command, term, term_len, environment, width, height, type);
stream = php_ssh2_exec_command(session, Z_RES_P(zsession)->handle, command, term, term_len, environment, width, height, type);
if (!stream) {
RETURN_FALSE;
}
@@ -987,7 +987,7 @@ static php_stream *php_ssh2_scp_xfer(LIBSSH2_SESSION *session, int resource_id,
channel_data->streamid = 0;
channel_data->is_blocking = 0;
channel_data->timeout = 0;
channel_data->session_rsrc = resource_id;
channel_data->session_rsrcid = resource_id;
channel_data->refcount = NULL;
stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r");
@@ -1236,7 +1236,7 @@ static php_stream *php_ssh2_direct_tcpip(LIBSSH2_SESSION *session, int resource_
channel_data->streamid = 0;
channel_data->is_blocking = 0;
channel_data->timeout = 0;
channel_data->session_rsrc = resource_id;
channel_data->session_rsrcid = resource_id;
channel_data->refcount = NULL;
stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
@@ -1337,7 +1337,7 @@ PHP_FUNCTION(ssh2_tunnel)
SSH2_FETCH_AUTHENTICATED_SESSION(session, zsession);
stream = php_ssh2_direct_tcpip(session, Z_LVAL_P(zsession), host, port);
stream = php_ssh2_direct_tcpip(session, Z_RES_P(zsession)->handle, host, port);
if (!stream) {
RETURN_FALSE;
}

24
tests/ssh2_shell.phpt Normal file
View File

@@ -0,0 +1,24 @@
--TEST--
ssh2_shell_test() - Tests opening a shell
--SKIPIF--
<?php require('ssh2_skip.inc'); ssh2t_needs_auth(); ?>
--FILE--
<?php require('ssh2_test.inc');
$ssh = ssh2_connect(TEST_SSH2_HOSTNAME, TEST_SSH2_PORT);
var_dump(ssh2t_auth($ssh));
$shell = ssh2_shell($ssh);
var_dump($shell);
fwrite( $shell, 'echo "foo bar"'.PHP_EOL);
sleep(1);
while($line = fgets($shell)) {
echo $line;
}
--EXPECTF--
bool(true)
resource(%d) of type (stream)
%a
foo bar
%a