SSH2: updates to openchannel refactoring

This commit is contained in:
terrafrost 2023-04-14 11:24:31 -05:00
parent 5fb084b04c
commit 184a984e97
3 changed files with 33 additions and 13 deletions

View File

@ -2752,9 +2752,9 @@ class SSH2
return false; return false;
} }
if ($this->isPTYOpen()) { //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.'); // 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); $this->openChannel(self::CHANNEL_EXEC);
@ -2836,6 +2836,16 @@ class SSH2
} }
} }
/**
* How many channels are currently open?
*
* @return int
*/
public function getOpenChannelCount()
{
return $this->channelCount;
}
/** /**
* Opens a channel * Opens a channel
* *
@ -2845,6 +2855,10 @@ class SSH2
*/ */
protected function openChannel($channel, $skip_extended = false) protected function openChannel($channel, $skip_extended = false)
{ {
if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_CLOSE) {
throw new \RuntimeException('Please close the channel (' . $channel . ') before trying to open it again');
}
$this->channelCount++; $this->channelCount++;
if ($this->channelCount > 1 && $this->errorOnMultipleChannels) { if ($this->channelCount > 1 && $this->errorOnMultipleChannels) {
@ -2892,10 +2906,6 @@ class SSH2
*/ */
public function openShell() public function openShell()
{ {
if ($this->isShellOpen()) {
return false;
}
if (!$this->isAuthenticated()) { if (!$this->isAuthenticated()) {
throw new InsufficientSetupException('Operation disallowed prior to login()'); throw new InsufficientSetupException('Operation disallowed prior to login()');
} }
@ -3060,7 +3070,7 @@ class SSH2
$channel = $this->get_interactive_channel(); $channel = $this->get_interactive_channel();
} }
if (!$this->isInteractiveChannelOpen($channel)) { if (!$this->isInteractiveChannelOpen($channel) && empty($this->channel_buffers[$channel])) {
if ($channel != self::CHANNEL_SHELL) { if ($channel != self::CHANNEL_SHELL) {
throw new InsufficientSetupException('Data is not available on channel'); throw new InsufficientSetupException('Data is not available on channel');
} elseif (!$this->openShell()) { } elseif (!$this->openShell()) {
@ -4111,6 +4121,8 @@ class SSH2
} }
$this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE; $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
$this->channelCount--;
if ($client_channel == $channel) { if ($client_channel == $channel) {
return true; return true;
} }
@ -4442,6 +4454,7 @@ class SSH2
} }
$this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE; $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
$this->channelCount--;
$this->curTimeout = 5; $this->curTimeout = 5;
@ -4913,6 +4926,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 * Allows you to set the terminal
* *

View File

@ -416,7 +416,7 @@ class SSH2Test extends PhpseclibFunctionalTestCase
public function testMultipleExecPty() public function testMultipleExecPty()
{ {
$this->expectException(\RuntimeException::class); $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(); $ssh = $this->getSSH2Login();

View File

@ -202,12 +202,11 @@ class SSH2UnitTest extends PhpseclibTestCase
{ {
$ssh = $this->getMockBuilder(SSH2::class) $ssh = $this->getMockBuilder(SSH2::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->setMethods(['__destruct', 'isShellOpen']) ->setMethods(['__destruct'])
->getMock(); ->getMock();
$ssh->expects($this->once()) $this->expectException(InsufficientSetupException::class);
->method('isShellOpen') $this->expectExceptionMessage('Operation disallowed prior to login()');
->willReturn(true);
$this->assertFalse($ssh->openShell()); $this->assertFalse($ssh->openShell());
} }