Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fix_SSH2_class] Introduce a fix for inconsistent return type problem." #1472

Open
wants to merge 1 commit into
base: 2.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions phpseclib/Exception/PhpSecLibException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace phpseclib\Exception;

use Exception;

class PhpSecLibException extends Exception implements PhpSecLibExceptionInterface
{
}
7 changes: 7 additions & 0 deletions phpseclib/Exception/PhpSecLibExceptionInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace phpseclib\Exception;

interface PhpSecLibExceptionInterface
{
}
20 changes: 20 additions & 0 deletions phpseclib/Net/Exception/InvalidPayloadException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace phpseclib\Net\Exception;

use phpseclib\Exception\PhpSecLibExceptionInterface;

class InvalidPayloadException extends NetException implements PhpSecLibExceptionInterface
{
public static function payloadTooShortException($payload, $expectedBits)
{
throw new self(
sprintf(
'The payload "%s" was too short (is: %d bits, should be at least: %d bits)',
$payload,
strlen($payload),
$expectedBits
)
);
}
}
29 changes: 29 additions & 0 deletions phpseclib/Net/Exception/KeyExchangeFailedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace phpseclib\Net\Exception;

use phpseclib\Exception\PhpSecLibException;
use phpseclib\Exception\PhpSecLibExceptionInterface;

class KeyExchangeFailedException extends PhpSecLibException implements PhpSecLibExceptionInterface
{
public static function fromPayload($payload)
{
throw new self(
sprintf(
'The key exchange failed (Payload: %s)',
$payload
)
);
}

public static function fromBadAlgorithm($badAlgorithm)
{
throw new self('Using a bad algorithm "%s"');
}

public static function fromUnreasonablePacketLength()
{
throw new self('Packet length during key exchange was unreasonable');
}
}
14 changes: 14 additions & 0 deletions phpseclib/Net/Exception/NetException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace phpseclib\Net\Exception;

use phpseclib\Exception\PhpSecLibException;
use phpseclib\Exception\PhpSecLibExceptionInterface;

class NetException extends PhpSecLibException implements PhpSecLibExceptionInterface
{
public static function withMessage($message)
{
throw new self($message);
}
}
9 changes: 9 additions & 0 deletions phpseclib/Net/Exception/NotImplementedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace phpseclib\Net\Exception;

use phpseclib\Exception\PhpSecLibExceptionInterface;

class NotImplementedException extends NetException implements PhpSecLibExceptionInterface
{
}
18 changes: 18 additions & 0 deletions phpseclib/Net/Exception/PacketCouldNotBeSentException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace phpseclib\Net\Exception;

use phpseclib\Exception\PhpSecLibExceptionInterface;

class PacketCouldNotBeSentException extends NetException implements PhpSecLibExceptionInterface
{
public static function fromPacket($packet)
{
throw new self(
sprintf(
'The package could not be sent (Content: %s)',
$packet
)
);
}
}
61 changes: 35 additions & 26 deletions phpseclib/Net/SSH2.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,13 @@
use phpseclib\Crypt\RSA;
use phpseclib\Crypt\TripleDES;
use phpseclib\Crypt\Twofish;
use phpseclib\Exception\PhpSecLibException;
use phpseclib\Math\BigInteger; // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
use phpseclib\Net\Exception\InvalidPayloadException;
use phpseclib\Net\Exception\KeyExchangeFailedException;
use phpseclib\Net\Exception\NetException;
use phpseclib\Net\Exception\NotImplementedException;
use phpseclib\Net\Exception\PacketCouldNotBeSentException;
use phpseclib\System\SSH\Agent;

/**
Expand Down Expand Up @@ -1268,11 +1274,13 @@ function _connect()
}

if (!$this->send_kex_first) {
$response = $this->_get_binary_packet();
if ($response === false) {
try {
$response = $this->_get_binary_packet();
} catch (PhpSecLibException $exception) {
$this->bitmap = 0;
user_error('Connection closed by server');
return false;

throw $exception;
}

if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
Expand All @@ -1281,7 +1289,7 @@ function _connect()
}

if (!$this->_key_exchange($response)) {
return false;
throw KeyExchangeFailedException::fromPayload($response);
}
}

Expand Down Expand Up @@ -3321,7 +3329,7 @@ function _get_binary_packet($skip_channel_filter = false)
if (!is_resource($this->fsock) || feof($this->fsock)) {
$this->bitmap = 0;
user_error('Connection closed prematurely');
return false;
throw NetException::withMessage('Connection closed prematurely');
}

$start = microtime(true);
Expand All @@ -3336,11 +3344,11 @@ function _get_binary_packet($skip_channel_filter = false)
}
if ($raw === false) {
user_error('Unable to decrypt content');
return false;
throw NetException::withMessage('Unable to decrypt content');
}

if (strlen($raw) < 5) {
return false;
throw InvalidPayloadException::payloadTooShortException($raw, 5);
}
extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5)));

Expand All @@ -3353,10 +3361,10 @@ function _get_binary_packet($skip_channel_filter = false)
if (!$this->bad_key_size_fix && $this->_bad_algorithm_candidate($this->decrypt->name) && !($this->bitmap & SSH2::MASK_LOGIN)) {
$this->bad_key_size_fix = true;
$this->_reset_connection(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
return false;
throw KeyExchangeFailedException::fromBadAlgorithm($this->decrypt->name);
}
user_error('Invalid size');
return false;
throw KeyExchangeFailedException::fromUnreasonablePacketLength();
}

$buffer = '';
Expand All @@ -3365,7 +3373,7 @@ function _get_binary_packet($skip_channel_filter = false)
if ($temp === false || feof($this->fsock)) {
$this->bitmap = 0;
user_error('Error reading from socket');
return false;
throw NetException::withMessage('Error reading from socket');
}
$buffer.= $temp;
$remaining_length-= strlen($temp);
Expand All @@ -3384,10 +3392,10 @@ function _get_binary_packet($skip_channel_filter = false)
if ($hmac === false || strlen($hmac) != $this->hmac_size) {
$this->bitmap = 0;
user_error('Error reading socket');
return false;
throw NetException::withMessage('Error reading from socket');
} elseif ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) {
user_error('Invalid HMAC');
return false;
throw NetException::withMessage('Invalid HMAC');
}
}

Expand Down Expand Up @@ -3424,32 +3432,32 @@ function _filter($payload, $skip_channel_filter)
case NET_SSH2_MSG_DISCONNECT:
$this->_string_shift($payload, 1);
if (strlen($payload) < 8) {
return false;
throw InvalidPayloadException::payloadTooShortException($payload, 8);
}
extract(unpack('Nreason_code/Nlength', $this->_string_shift($payload, 8)));
$this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n" . $this->_string_shift($payload, $length);
$this->bitmap = 0;
return false;
return '';
case NET_SSH2_MSG_IGNORE:
$payload = $this->_get_binary_packet($skip_channel_filter);
break;
case NET_SSH2_MSG_DEBUG:
$this->_string_shift($payload, 2);
if (strlen($payload) < 4) {
return false;
throw InvalidPayloadException::payloadTooShortException($payload, 4);
}
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$this->errors[] = 'SSH_MSG_DEBUG: ' . $this->_string_shift($payload, $length);
$payload = $this->_get_binary_packet($skip_channel_filter);
break;
case NET_SSH2_MSG_UNIMPLEMENTED:
return false;
throw new NotImplementedException();
case NET_SSH2_MSG_KEXINIT:
if ($this->session_id !== false) {
$this->send_kex_first = false;
if (!$this->_key_exchange($payload)) {
$this->bitmap = 0;
return false;
throw KeyExchangeFailedException::fromPayload($payload);
}
$payload = $this->_get_binary_packet($skip_channel_filter);
}
Expand All @@ -3459,7 +3467,7 @@ function _filter($payload, $skip_channel_filter)
if (($this->bitmap & self::MASK_CONNECTED) && !$this->isAuthenticated() && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
$this->_string_shift($payload, 1);
if (strlen($payload) < 4) {
return false;
throw InvalidPayloadException::payloadTooShortException($payload, 4);
}
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$this->banner_message = $this->_string_shift($payload, $length);
Expand All @@ -3482,7 +3490,7 @@ function _filter($payload, $skip_channel_filter)
break;
case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
if (strlen($payload) < 4) {
return false;
throw InvalidPayloadException::payloadTooShortException($payload, 4);
}
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$this->errors[] = 'SSH_MSG_GLOBAL_REQUEST: ' . $this->_string_shift($payload, $length);
Expand All @@ -3496,12 +3504,12 @@ function _filter($payload, $skip_channel_filter)
case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
$this->_string_shift($payload, 1);
if (strlen($payload) < 4) {
return false;
throw InvalidPayloadException::payloadTooShortException($payload, 4);
}
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$data = $this->_string_shift($payload, $length);
if (strlen($payload) < 4) {
return false;
throw InvalidPayloadException::payloadTooShortException($payload, 4);
}
extract(unpack('Nserver_channel', $this->_string_shift($payload, 4)));
switch ($data) {
Expand All @@ -3511,7 +3519,7 @@ function _filter($payload, $skip_channel_filter)
$new_channel = self::CHANNEL_AGENT_FORWARD;

if (strlen($payload) < 8) {
return false;
throw InvalidPayloadException::payloadTooShortException($payload, 8);
}
extract(unpack('Nremote_window_size', $this->_string_shift($payload, 4)));
extract(unpack('Nremote_maximum_packet_size', $this->_string_shift($payload, 4)));
Expand All @@ -3534,7 +3542,7 @@ function _filter($payload, $skip_channel_filter)
$this->server_channels[$new_channel] = $server_channel;
$this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION;
if (!$this->_send_binary_packet($packet)) {
return false;
throw PacketCouldNotBeSentException::fromPacket($packet);
}
}
break;
Expand All @@ -3551,21 +3559,22 @@ function _filter($payload, $skip_channel_filter)
);

if (!$this->_send_binary_packet($packet)) {
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
throw PacketCouldNotBeSentException::fromPacket($packet);
}
}
$payload = $this->_get_binary_packet($skip_channel_filter);
break;
case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
$this->_string_shift($payload, 1);
if (strlen($payload) < 8) {
return false;
throw InvalidPayloadException::payloadTooShortException($payload, 8);
}
extract(unpack('Nchannel', $this->_string_shift($payload, 4)));
extract(unpack('Nwindow_size', $this->_string_shift($payload, 4)));
$this->window_size_client_to_server[$channel]+= $window_size;

$payload = ($this->bitmap & self::MASK_WINDOW_ADJUST) ? true : $this->_get_binary_packet($skip_channel_filter);
$payload = ($this->bitmap & self::MASK_WINDOW_ADJUST) ? '' : $this->_get_binary_packet($skip_channel_filter);
}
}

Expand Down