mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-27 03:42:40 +00:00
Merge branch '3.0-openchannel' into master-openchannel
This commit is contained in:
commit
52c85c9935
@ -2455,9 +2455,9 @@ class SSH2
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->isPTYOpen()) {
|
||||
throw new RuntimeException('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.');
|
||||
}
|
||||
//if ($this->isPTYOpen()) {
|
||||
// throw new RuntimeException('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.');
|
||||
//}
|
||||
|
||||
$this->openChannel(self::CHANNEL_EXEC);
|
||||
|
||||
@ -2539,15 +2539,29 @@ class SSH2
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How many channels are currently open?
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getOpenChannelCount()
|
||||
{
|
||||
return $this->channelCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a channel
|
||||
*/
|
||||
protected function openChannel(string $channel, bool $skip_extended = false): bool
|
||||
protected function openChannel(int $channel, bool $skip_extended = false): bool
|
||||
{
|
||||
if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] != MessageType::CHANNEL_CLOSE) {
|
||||
throw new RuntimeException('Please close the channel (' . $channel . ') before trying to open it again');
|
||||
}
|
||||
|
||||
$this->channelCount++;
|
||||
|
||||
if ($this->channelCount > 1 && $this->errorOnMultipleChannels) {
|
||||
throw new \RuntimeException("Ubuntu's OpenSSH from 5.8 to 6.9 doesn't work with multiple channels");
|
||||
throw new RuntimeException("Ubuntu's OpenSSH from 5.8 to 6.9 doesn't work with multiple channels");
|
||||
}
|
||||
|
||||
// RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to
|
||||
@ -2561,7 +2575,7 @@ class SSH2
|
||||
|
||||
$packet = Strings::packSSH2(
|
||||
'CsN3',
|
||||
SSH2MessageType::CHANNEL_OPEN,
|
||||
MessageType::CHANNEL_OPEN,
|
||||
'session',
|
||||
$channel,
|
||||
$this->window_size_server_to_client[$channel],
|
||||
@ -2570,7 +2584,7 @@ class SSH2
|
||||
|
||||
$this->send_binary_packet($packet);
|
||||
|
||||
$this->channel_status[$channel] = SSH2MessageType::CHANNEL_OPEN;
|
||||
$this->channel_status[$channel] = MessageType::CHANNEL_OPEN;
|
||||
|
||||
return $this->get_channel_packet($channel, $skip_extended);
|
||||
}
|
||||
@ -2590,10 +2604,6 @@ class SSH2
|
||||
*/
|
||||
public function openShell(): bool
|
||||
{
|
||||
if ($this->isShellOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->isAuthenticated()) {
|
||||
throw new InsufficientSetupException('Operation disallowed prior to login()');
|
||||
}
|
||||
@ -2751,7 +2761,7 @@ class SSH2
|
||||
$channel = $this->get_interactive_channel();
|
||||
}
|
||||
|
||||
if (!$this->isInteractiveChannelOpen($channel)) {
|
||||
if (!$this->isInteractiveChannelOpen($channel) && empty($this->channel_buffers[$channel])) {
|
||||
if ($channel != self::CHANNEL_SHELL) {
|
||||
throw new InsufficientSetupException('Data is not available on channel');
|
||||
} elseif (!$this->openShell()) {
|
||||
@ -3733,7 +3743,7 @@ class SSH2
|
||||
}
|
||||
}
|
||||
|
||||
// ie. $this->channel_status[$channel] == SSHMsg::CHANNEL_DATA
|
||||
// ie. $this->channel_status[$channel] == MessageType::CHANNEL_DATA
|
||||
|
||||
switch ($type) {
|
||||
case MessageType::CHANNEL_DATA:
|
||||
@ -3771,6 +3781,8 @@ class SSH2
|
||||
}
|
||||
|
||||
$this->channel_status[$channel] = MessageType::CHANNEL_CLOSE;
|
||||
$this->channelCount--;
|
||||
|
||||
if ($client_channel == $channel) {
|
||||
return true;
|
||||
}
|
||||
@ -4085,6 +4097,7 @@ class SSH2
|
||||
}
|
||||
|
||||
$this->channel_status[$client_channel] = MessageType::CHANNEL_CLOSE;
|
||||
$this->channelCount--;
|
||||
|
||||
$this->curTimeout = 5;
|
||||
|
||||
@ -4503,6 +4516,14 @@ class SSH2
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Force multiple channels (even if phpseclib has decided to disable them)
|
||||
*/
|
||||
public function forceMultipleChannels()
|
||||
{
|
||||
$this->errorOnMultipleChannels = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows you to set the terminal
|
||||
*/
|
||||
|
@ -412,7 +412,7 @@ class SSH2Test extends PhpseclibFunctionalTestCase
|
||||
public function testMultipleExecPty(): void
|
||||
{
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.');
|
||||
$this->expectExceptionMessage('Please close the channel (1) before trying to open it again');
|
||||
|
||||
$ssh = $this->getSSH2Login();
|
||||
|
||||
@ -538,4 +538,21 @@ class SSH2Test extends PhpseclibFunctionalTestCase
|
||||
'Failed asserting that exec channel identifier is maintained as last opened channel.'
|
||||
);
|
||||
}
|
||||
|
||||
public function testReadingOfClosedChannel()
|
||||
{
|
||||
$ssh = $this->getSSH2Login();
|
||||
$this->assertSame(0, $ssh->getOpenChannelCount());
|
||||
$ssh->enablePTY();
|
||||
$ssh->exec('ping -c 3 127.0.0.1; exit');
|
||||
$ssh->write("ping 127.0.0.2\n", SSH2::CHANNEL_SHELL);
|
||||
$ssh->setTimeout(3);
|
||||
$output = $ssh->read('', SSH2::READ_SIMPLE, SSH2::CHANNEL_SHELL);
|
||||
$this->assertStringContainsString('PING 127.0.0.2', $output);
|
||||
$output = $ssh->read('', SSH2::READ_SIMPLE, SSH2::CHANNEL_EXEC);
|
||||
$this->assertStringContainsString('PING 127.0.0.1', $output);
|
||||
$this->assertSame(1, $ssh->getOpenChannelCount());
|
||||
$ssh->reset(SSH2::CHANNEL_SHELL);
|
||||
$this->assertSame(0, $ssh->getOpenChannelCount());
|
||||
}
|
||||
}
|
||||
|
@ -199,12 +199,11 @@ class SSH2UnitTest extends PhpseclibTestCase
|
||||
{
|
||||
$ssh = $this->getMockBuilder(SSH2::class)
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['__destruct', 'isShellOpen'])
|
||||
->setMethods(['__destruct'])
|
||||
->getMock();
|
||||
|
||||
$ssh->expects($this->once())
|
||||
->method('isShellOpen')
|
||||
->willReturn(true);
|
||||
$this->expectException(InsufficientSetupException::class);
|
||||
$this->expectExceptionMessage('Operation disallowed prior to login()');
|
||||
|
||||
$this->assertFalse($ssh->openShell());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user