1
0
mirror of https://github.com/danog/phpseclib.git synced 2024-12-12 09:09:39 +01:00

Merge branch '2.0' into 3.0

This commit is contained in:
terrafrost 2021-10-11 09:15:37 -05:00
commit a2c30f9d33

View File

@ -2744,6 +2744,12 @@ class SSH2
$this->send_binary_packet($packet); $this->send_binary_packet($packet);
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST;
if (!$this->get_channel_packet(self::CHANNEL_SHELL)) {
throw new \RuntimeException('Unable to request pty');
}
$packet = Strings::packSSH2( $packet = Strings::packSSH2(
'CNsb', 'CNsb',
NET_SSH2_MSG_CHANNEL_REQUEST, NET_SSH2_MSG_CHANNEL_REQUEST,
@ -2753,7 +2759,12 @@ class SSH2
); );
$this->send_binary_packet($packet); $this->send_binary_packet($packet);
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_IGNORE; $response = $this->get_channel_packet(self::CHANNEL_SHELL);
if ($response === false) {
throw new \RuntimeException('Unable to request shell');
}
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA;
$this->bitmap |= self::MASK_SHELL; $this->bitmap |= self::MASK_SHELL;
@ -3187,7 +3198,7 @@ class SSH2
if (!is_resource($this->fsock) || feof($this->fsock)) { if (!is_resource($this->fsock) || feof($this->fsock)) {
$this->bitmap = 0; $this->bitmap = 0;
throw new ConnectionClosedException('Connection closed prematurely'); throw new ConnectionClosedException('Connection closed (by server) prematurely');
} }
$start = microtime(true); $start = microtime(true);
@ -3643,7 +3654,20 @@ class SSH2
protected function get_channel_packet($client_channel, $skip_extended = false) protected function get_channel_packet($client_channel, $skip_extended = false)
{ {
if (!empty($this->channel_buffers[$client_channel])) { if (!empty($this->channel_buffers[$client_channel])) {
return array_shift($this->channel_buffers[$client_channel]); switch ($this->channel_status[$client_channel]) {
case NET_SSH2_MSG_CHANNEL_REQUEST:
foreach ($this->channel_buffers[$client_channel] as $i => $packet) {
switch (ord($packet[0])) {
case NET_SSH2_MSG_CHANNEL_SUCCESS:
case NET_SSH2_MSG_CHANNEL_FAILURE:
unset($this->channel_buffers[$client_channel][$i]);
return substr($packet, 1);
}
}
break;
default:
return substr(array_shift($this->channel_buffers[$client_channel]), 1);
}
} }
while (true) { while (true) {
@ -3698,10 +3722,7 @@ class SSH2
if ($client_channel == $channel && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA) { if ($client_channel == $channel && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA) {
return $data; return $data;
} }
if (!isset($this->channel_buffers[$channel])) { $this->channel_buffers[$channel][] = chr($type) . $data;
$this->channel_buffers[$channel] = [];
}
$this->channel_buffers[$channel][] = $data;
continue 2; continue 2;
case NET_SSH2_MSG_CHANNEL_REQUEST: case NET_SSH2_MSG_CHANNEL_REQUEST:
@ -3772,22 +3793,16 @@ class SSH2
return $this->get_channel_packet($client_channel, $skip_extended); return $this->get_channel_packet($client_channel, $skip_extended);
} }
break; break;
case NET_SSH2_MSG_IGNORE:
switch ($type) {
case NET_SSH2_MSG_CHANNEL_SUCCESS:
//$this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_DATA;
continue 3;
case NET_SSH2_MSG_CHANNEL_FAILURE:
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
throw new \RuntimeException('Error opening channel');
}
break;
case NET_SSH2_MSG_CHANNEL_REQUEST: case NET_SSH2_MSG_CHANNEL_REQUEST:
switch ($type) { switch ($type) {
case NET_SSH2_MSG_CHANNEL_SUCCESS: case NET_SSH2_MSG_CHANNEL_SUCCESS:
return true; return true;
case NET_SSH2_MSG_CHANNEL_FAILURE: case NET_SSH2_MSG_CHANNEL_FAILURE:
return false; return false;
case NET_SSH2_MSG_CHANNEL_DATA:
list($data) = Strings::unpackSSH2('s', $response);
$this->channel_buffers[$channel][] = chr($type) . $data;
return $this->get_channel_packet($client_channel, $skip_extended);
default: default:
$this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
throw new \RuntimeException('Unable to fulfill channel request'); throw new \RuntimeException('Unable to fulfill channel request');
@ -3801,10 +3816,6 @@ class SSH2
switch ($type) { switch ($type) {
case NET_SSH2_MSG_CHANNEL_DATA: case NET_SSH2_MSG_CHANNEL_DATA:
//if ($this->channel_status[$channel] == NET_SSH2_MSG_IGNORE) {
// $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_DATA;
//}
/* /*
if ($channel == self::CHANNEL_EXEC) { if ($channel == self::CHANNEL_EXEC) {
// SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server // SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server
@ -3827,10 +3838,7 @@ class SSH2
if ($client_channel == $channel) { if ($client_channel == $channel) {
return $data; return $data;
} }
if (!isset($this->channel_buffers[$channel])) { $this->channel_buffers[$channel][] = chr($type) . $data;
$this->channel_buffers[$channel] = [];
}
$this->channel_buffers[$channel][] = $data;
break; break;
case NET_SSH2_MSG_CHANNEL_CLOSE: case NET_SSH2_MSG_CHANNEL_CLOSE:
$this->curTimeout = 5; $this->curTimeout = 5;
@ -3850,7 +3858,7 @@ class SSH2
break; break;
default: default:
$this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
throw new \RuntimeException('Error reading channel data'); throw new \RuntimeException("Error reading channel data ($type)");
} }
} }
} }