mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-25 03:16:02 +00:00
Merge branch '1.0' of https://github.com/phpseclib/phpseclib into openssl-support
Conflicts: phpseclib/Net/SSH2.php
This commit is contained in:
commit
e510dc878b
@ -1,5 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.3.10 - 2015-02-04
|
||||||
|
|
||||||
|
- simplify SSH2 window size handling ([#538](https://github.com/phpseclib/phpseclib/pull/538))
|
||||||
|
- slightly relax the conditions under which OpenSSL is used ([#598](https://github.com/phpseclib/phpseclib/pull/598))
|
||||||
|
- fix issue with empty constructed context-specific tags in ASN1 ([#606](https://github.com/phpseclib/phpseclib/pull/606))
|
||||||
|
|
||||||
## 0.3.9 - 2014-11-09
|
## 0.3.9 - 2014-11-09
|
||||||
|
|
||||||
- PHP 5.6 improvements ([#482](https://github.com/phpseclib/phpseclib/pull/482), [#491](https://github.com/phpseclib/phpseclib/issues/491))
|
- PHP 5.6 improvements ([#482](https://github.com/phpseclib/phpseclib/pull/482), [#491](https://github.com/phpseclib/phpseclib/issues/491))
|
||||||
|
@ -1589,7 +1589,7 @@ class File_X509
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($map) {
|
} else {
|
||||||
$value = base64_encode($value);
|
$value = base64_encode($value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1612,6 +1612,10 @@ class File_X509
|
|||||||
if (is_array($extensions)) {
|
if (is_array($extensions)) {
|
||||||
$size = count($extensions);
|
$size = count($extensions);
|
||||||
for ($i = 0; $i < $size; $i++) {
|
for ($i = 0; $i < $size; $i++) {
|
||||||
|
if (is_object($extensions[$i]) && strtolower(get_class($extensions[$i])) == 'file_asn1_element') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$id = $extensions[$i]['extnId'];
|
$id = $extensions[$i]['extnId'];
|
||||||
$value = &$extensions[$i]['extnValue'];
|
$value = &$extensions[$i]['extnValue'];
|
||||||
|
|
||||||
|
@ -99,6 +99,7 @@ define('NET_SSH2_MASK_WINDOW_ADJUST', 0x00000020);
|
|||||||
define('NET_SSH2_CHANNEL_EXEC', 0); // PuTTy uses 0x100
|
define('NET_SSH2_CHANNEL_EXEC', 0); // PuTTy uses 0x100
|
||||||
define('NET_SSH2_CHANNEL_SHELL', 1);
|
define('NET_SSH2_CHANNEL_SHELL', 1);
|
||||||
define('NET_SSH2_CHANNEL_SUBSYSTEM', 2);
|
define('NET_SSH2_CHANNEL_SUBSYSTEM', 2);
|
||||||
|
define('NET_SSH2_CHANNEL_AGENT_FORWARD', 3);
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
@ -803,21 +804,6 @@ class Net_SSH2
|
|||||||
*/
|
*/
|
||||||
var $port;
|
var $port;
|
||||||
|
|
||||||
/**
|
|
||||||
* Timeout for initial connection
|
|
||||||
*
|
|
||||||
* Set by the constructor call. Calling setTimeout() is optional. If it's not called functions like
|
|
||||||
* exec() won't timeout unless some PHP setting forces it too. The timeout specified in the constructor,
|
|
||||||
* however, is non-optional. There will be a timeout, whether or not you set it. If you don't it'll be
|
|
||||||
* 10 seconds. It is used by fsockopen() and the initial stream_select in that function.
|
|
||||||
*
|
|
||||||
* @see Net_SSH2::Net_SSH2()
|
|
||||||
* @see Net_SSH2::_connect()
|
|
||||||
* @var Integer
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $connectionTimeout;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of columns for terminal window size
|
* Number of columns for terminal window size
|
||||||
*
|
*
|
||||||
@ -850,6 +836,14 @@ class Net_SSH2
|
|||||||
*/
|
*/
|
||||||
var $crypto_engine = false;
|
var $crypto_engine = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario
|
||||||
|
*
|
||||||
|
* @var System_SSH_Agent
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $agent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
@ -953,7 +947,7 @@ class Net_SSH2
|
|||||||
|
|
||||||
$this->host = $host;
|
$this->host = $host;
|
||||||
$this->port = $port;
|
$this->port = $port;
|
||||||
$this->connectionTimeout = $timeout;
|
$this->timeout = $timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -984,36 +978,24 @@ class Net_SSH2
|
|||||||
|
|
||||||
$this->bitmap |= NET_SSH2_MASK_CONSTRUCTOR;
|
$this->bitmap |= NET_SSH2_MASK_CONSTRUCTOR;
|
||||||
|
|
||||||
$timeout = $this->connectionTimeout;
|
$this->curTimeout = $this->timeout;
|
||||||
|
|
||||||
$host = $this->host . ':' . $this->port;
|
$host = $this->host . ':' . $this->port;
|
||||||
|
|
||||||
$this->last_packet = strtok(microtime(), ' ') + strtok(''); // == microtime(true) in PHP5
|
$this->last_packet = strtok(microtime(), ' ') + strtok(''); // == microtime(true) in PHP5
|
||||||
|
|
||||||
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
|
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
|
||||||
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $timeout);
|
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout);
|
||||||
if (!$this->fsock) {
|
if (!$this->fsock) {
|
||||||
user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
|
user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
|
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
|
||||||
|
|
||||||
$timeout-= $elapsed;
|
$this->curTimeout-= $elapsed;
|
||||||
|
|
||||||
if ($timeout <= 0) {
|
if ($this->curTimeout <= 0) {
|
||||||
user_error("Cannot connect to $host. Timeout error");
|
$this->is_timeout = true;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$read = array($this->fsock);
|
|
||||||
$write = $except = null;
|
|
||||||
|
|
||||||
$sec = floor($timeout);
|
|
||||||
$usec = 1000000 * ($timeout - $sec);
|
|
||||||
|
|
||||||
// on windows this returns a "Warning: Invalid CRT parameters detected" error
|
|
||||||
// the !count() is done as a workaround for <https://bugs.php.net/42682>
|
|
||||||
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
|
|
||||||
user_error("Cannot connect to $host. Banner timeout");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,6 +1013,27 @@ class Net_SSH2
|
|||||||
$extra.= $temp;
|
$extra.= $temp;
|
||||||
$temp = '';
|
$temp = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->curTimeout) {
|
||||||
|
if ($this->curTimeout < 0) {
|
||||||
|
$this->is_timeout = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$read = array($this->fsock);
|
||||||
|
$write = $except = null;
|
||||||
|
$start = strtok(microtime(), ' ') + strtok('');
|
||||||
|
$sec = floor($this->curTimeout);
|
||||||
|
$usec = 1000000 * ($this->curTimeout - $sec);
|
||||||
|
// on windows this returns a "Warning: Invalid CRT parameters detected" error
|
||||||
|
// the !count() is done as a workaround for <https://bugs.php.net/42682>
|
||||||
|
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
|
||||||
|
$this->is_timeout = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
|
||||||
|
$this->curTimeout-= $elapsed;
|
||||||
|
}
|
||||||
|
|
||||||
$temp.= fgets($this->fsock, 255);
|
$temp.= fgets($this->fsock, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2178,6 +2181,7 @@ class Net_SSH2
|
|||||||
*/
|
*/
|
||||||
function _ssh_agent_login($username, $agent)
|
function _ssh_agent_login($username, $agent)
|
||||||
{
|
{
|
||||||
|
$this->agent = $agent;
|
||||||
$keys = $agent->requestIdentities();
|
$keys = $agent->requestIdentities();
|
||||||
foreach ($keys as $key) {
|
foreach ($keys as $key) {
|
||||||
if ($this->_privatekey_login($username, $key)) {
|
if ($this->_privatekey_login($username, $key)) {
|
||||||
@ -2357,6 +2361,7 @@ class Net_SSH2
|
|||||||
if (!$this->_send_binary_packet($packet)) {
|
if (!$this->_send_binary_packet($packet)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
user_error('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
@ -2387,6 +2392,7 @@ class Net_SSH2
|
|||||||
// "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA. RFC4254#section-5.2 corroborates.
|
// "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA. RFC4254#section-5.2 corroborates.
|
||||||
$packet = pack('CNNa*CNa*',
|
$packet = pack('CNNa*CNa*',
|
||||||
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_EXEC], strlen('exec'), 'exec', 1, strlen($command), $command);
|
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_EXEC], strlen('exec'), 'exec', 1, strlen($command), $command);
|
||||||
|
|
||||||
if (!$this->_send_binary_packet($packet)) {
|
if (!$this->_send_binary_packet($packet)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2523,6 +2529,24 @@ class Net_SSH2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an available open channel
|
||||||
|
*
|
||||||
|
* @return Integer
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function _get_open_channel()
|
||||||
|
{
|
||||||
|
$channel = NET_SSH2_CHANNEL_EXEC;
|
||||||
|
do {
|
||||||
|
if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_OPEN) {
|
||||||
|
return $channel;
|
||||||
|
}
|
||||||
|
} while ($channel++ < NET_SSH2_CHANNEL_SUBSYSTEM);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the output of an interactive shell
|
* Returns the output of an interactive shell
|
||||||
*
|
*
|
||||||
@ -2881,18 +2905,41 @@ class Net_SSH2
|
|||||||
case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
|
case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
|
||||||
$this->_string_shift($payload, 1);
|
$this->_string_shift($payload, 1);
|
||||||
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
|
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
|
||||||
$this->errors[] = 'SSH_MSG_CHANNEL_OPEN: ' . utf8_decode($this->_string_shift($payload, $length));
|
$data = $this->_string_shift($payload, $length);
|
||||||
|
|
||||||
$this->_string_shift($payload, 4); // skip over client channel
|
|
||||||
extract(unpack('Nserver_channel', $this->_string_shift($payload, 4)));
|
extract(unpack('Nserver_channel', $this->_string_shift($payload, 4)));
|
||||||
|
switch($data) {
|
||||||
|
case 'auth-agent':
|
||||||
|
case 'auth-agent@openssh.com':
|
||||||
|
if (isset($this->agent)) {
|
||||||
|
$new_channel = NET_SSH2_CHANNEL_AGENT_FORWARD;
|
||||||
|
|
||||||
|
extract(unpack('Nremote_window_size', $this->_string_shift($payload, 4)));
|
||||||
|
extract(unpack('Nremote_maximum_packet_size', $this->_string_shift($payload, 4)));
|
||||||
|
|
||||||
|
$this->packet_size_client_to_server[$new_channel] = $remote_window_size;
|
||||||
|
$this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size;
|
||||||
|
$this->window_size_client_to_server[$new_channel] = $this->window_size;
|
||||||
|
|
||||||
|
$packet_size = 0x4000;
|
||||||
|
|
||||||
|
$packet = pack('CN4',
|
||||||
|
NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, $server_channel, $new_channel, $packet_size, $packet_size);
|
||||||
|
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
$packet = pack('CN3a*Na*',
|
$packet = pack('CN3a*Na*',
|
||||||
NET_SSH2_MSG_REQUEST_FAILURE, $server_channel, NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, 0, '', 0, '');
|
NET_SSH2_MSG_REQUEST_FAILURE, $server_channel, NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, 0, '', 0, '');
|
||||||
|
|
||||||
if (!$this->_send_binary_packet($packet)) {
|
if (!$this->_send_binary_packet($packet)) {
|
||||||
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$payload = $this->_get_binary_packet();
|
$payload = $this->_get_binary_packet();
|
||||||
break;
|
break;
|
||||||
case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
|
case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
|
||||||
@ -3029,8 +3076,16 @@ class Net_SSH2
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Ctype/Nchannel', $this->_string_shift($response, 5)));
|
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||||
|
|
||||||
|
if ($type == NET_SSH2_MSG_CHANNEL_OPEN) {
|
||||||
|
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||||
|
} else {
|
||||||
|
extract(unpack('Nchannel', $this->_string_shift($response, 4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// will not be setup yet on incoming channel open request
|
||||||
|
if (isset($channel) && isset($this->channel_status[$channel]) && isset($this->window_size_server_to_client[$channel])) {
|
||||||
$this->window_size_server_to_client[$channel]-= strlen($response);
|
$this->window_size_server_to_client[$channel]-= strlen($response);
|
||||||
|
|
||||||
// resize the window, if appropriate
|
// resize the window, if appropriate
|
||||||
@ -3052,7 +3107,9 @@ class Net_SSH2
|
|||||||
$this->window_size_client_to_server[$channel] = $window_size;
|
$this->window_size_client_to_server[$channel] = $window_size;
|
||||||
$temp = unpack('Npacket_size_client_to_server', $this->_string_shift($response, 4));
|
$temp = unpack('Npacket_size_client_to_server', $this->_string_shift($response, 4));
|
||||||
$this->packet_size_client_to_server[$channel] = $temp['packet_size_client_to_server'];
|
$this->packet_size_client_to_server[$channel] = $temp['packet_size_client_to_server'];
|
||||||
return $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended);
|
$result = $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended);
|
||||||
|
$this->_on_channel_open();
|
||||||
|
return $result;
|
||||||
//case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
|
//case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
|
||||||
default:
|
default:
|
||||||
user_error('Unable to open channel');
|
user_error('Unable to open channel');
|
||||||
@ -3072,6 +3129,7 @@ class Net_SSH2
|
|||||||
case NET_SSH2_MSG_CHANNEL_CLOSE:
|
case NET_SSH2_MSG_CHANNEL_CLOSE:
|
||||||
return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended);
|
return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ie. $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA
|
// ie. $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA
|
||||||
|
|
||||||
@ -3088,6 +3146,15 @@ class Net_SSH2
|
|||||||
*/
|
*/
|
||||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||||
$data = $this->_string_shift($response, $length);
|
$data = $this->_string_shift($response, $length);
|
||||||
|
|
||||||
|
if ($channel == NET_SSH2_CHANNEL_AGENT_FORWARD) {
|
||||||
|
$agent_response = $this->agent->_forward_data($data);
|
||||||
|
if (!is_bool($agent_response)) {
|
||||||
|
$this->_send_channel_packet($channel, $agent_response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ($client_channel == $channel) {
|
if ($client_channel == $channel) {
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
@ -3524,6 +3591,22 @@ class Net_SSH2
|
|||||||
return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT);
|
return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for agent->_on_channel_open()
|
||||||
|
*
|
||||||
|
* Used when channels are created to inform agent
|
||||||
|
* of said channel opening. Must be called after
|
||||||
|
* channel open confirmation received
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _on_channel_open()
|
||||||
|
{
|
||||||
|
if (isset($this->agent)) {
|
||||||
|
$this->agent->_on_channel_open($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all errors
|
* Returns all errors
|
||||||
*
|
*
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP ssh-agent client.
|
* Pure-PHP ssh-agent client.
|
||||||
*
|
*
|
||||||
@ -63,6 +64,20 @@ define('SYSTEM_SSH_AGENT_FAILURE', 5);
|
|||||||
define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13);
|
define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13);
|
||||||
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
|
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
|
||||||
define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14);
|
define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14);
|
||||||
|
|
||||||
|
|
||||||
|
/**@+
|
||||||
|
* Agent forwarding status
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
// no forwarding requested and not active
|
||||||
|
define('SYSTEM_SSH_AGENT_FORWARD_NONE', 0);
|
||||||
|
// request agent forwarding when opportune
|
||||||
|
define('SYSTEM_SSH_AGENT_FORWARD_REQUEST', 1);
|
||||||
|
// forwarding has been request and is active
|
||||||
|
define('SYSTEM_SSH_AGENT_FORWARD_ACTIVE', 2);
|
||||||
|
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -225,6 +240,29 @@ class System_SSH_Agent
|
|||||||
*/
|
*/
|
||||||
var $fsock;
|
var $fsock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Agent forwarding status
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $forward_status = SYSTEM_SSH_AGENT_FORWARD_NONE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer for accumulating forwarded authentication
|
||||||
|
* agent data arriving on SSH data channel destined
|
||||||
|
* for agent unix socket
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $socket_buffer = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracking the number of bytes we are expecting
|
||||||
|
* to arrive for the agent socket on the SSH data
|
||||||
|
* channel
|
||||||
|
*/
|
||||||
|
var $expected_bytes = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor
|
* Default Constructor
|
||||||
*
|
*
|
||||||
@ -310,4 +348,107 @@ class System_SSH_Agent
|
|||||||
|
|
||||||
return $identities;
|
return $identities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal that agent forwarding should
|
||||||
|
* be requested when a channel is opened
|
||||||
|
*
|
||||||
|
* @param Net_SSH2 $ssh
|
||||||
|
* @return Boolean
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function startSSHForwarding($ssh)
|
||||||
|
{
|
||||||
|
if ($this->forward_status == SYSTEM_SSH_AGENT_FORWARD_NONE) {
|
||||||
|
$this->forward_status = SYSTEM_SSH_AGENT_FORWARD_REQUEST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request agent forwarding of remote server
|
||||||
|
*
|
||||||
|
* @param Net_SSH2 $ssh
|
||||||
|
* @return Boolean
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _request_forwarding($ssh)
|
||||||
|
{
|
||||||
|
$request_channel = $ssh->_get_open_channel();
|
||||||
|
if ($request_channel === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$packet = pack('CNNa*C',
|
||||||
|
NET_SSH2_MSG_CHANNEL_REQUEST, $ssh->server_channels[$request_channel], strlen('auth-agent-req@openssh.com'), 'auth-agent-req@openssh.com', 1);
|
||||||
|
|
||||||
|
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
||||||
|
|
||||||
|
if (!$ssh->_send_binary_packet($packet)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $ssh->_get_channel_packet($request_channel);
|
||||||
|
if ($response === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||||
|
$this->forward_status = SYSTEM_SSH_AGENT_FORWARD_ACTIVE;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On successful channel open
|
||||||
|
*
|
||||||
|
* This method is called upon successful channel
|
||||||
|
* open to give the SSH Agent an opportunity
|
||||||
|
* to take further action. i.e. request agent forwarding
|
||||||
|
*
|
||||||
|
* @param Net_SSH2 $ssh
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _on_channel_open($ssh)
|
||||||
|
{
|
||||||
|
if ($this->forward_status == SYSTEM_SSH_AGENT_FORWARD_REQUEST) {
|
||||||
|
$this->_request_forwarding($ssh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forward data to SSH Agent and return data reply
|
||||||
|
*
|
||||||
|
* @param String $data
|
||||||
|
* @return data from SSH Agent
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _forward_data($data)
|
||||||
|
{
|
||||||
|
if ($this->expected_bytes > 0) {
|
||||||
|
$this->socket_buffer.= $data;
|
||||||
|
$this->expected_bytes -= strlen($data);
|
||||||
|
} else {
|
||||||
|
$agent_data_bytes = current(unpack('N', $data));
|
||||||
|
$current_data_bytes = strlen($data);
|
||||||
|
$this->socket_buffer = $data;
|
||||||
|
if ($current_data_bytes != $agent_data_bytes + 4) {
|
||||||
|
$this->expected_bytes = ($agent_data_bytes + 4) - $current_data_bytes;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
|
||||||
|
user_error('Connection closed attempting to forward data to SSH agent');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->socket_buffer = '';
|
||||||
|
$this->expected_bytes = 0;
|
||||||
|
|
||||||
|
$agent_reply_bytes = current(unpack('N', fread($this->fsock, 4)));
|
||||||
|
|
||||||
|
$agent_reply_data = fread($this->fsock, $agent_reply_bytes);
|
||||||
|
$agent_reply_data = current(unpack('a*', $agent_reply_data));
|
||||||
|
|
||||||
|
return pack('Na*', $agent_reply_bytes, $agent_reply_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,5 +27,26 @@ class Functional_Net_SSH2AgentTest extends PhpseclibFunctionalTestCase
|
|||||||
$ssh->login($this->getEnv('SSH_USERNAME'), $agent),
|
$ssh->login($this->getEnv('SSH_USERNAME'), $agent),
|
||||||
'SSH2 login using Agent failed.'
|
'SSH2 login using Agent failed.'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return array('ssh' => $ssh, 'ssh-agent' => $agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testAgentLogin
|
||||||
|
*/
|
||||||
|
public function testAgentForward($args)
|
||||||
|
{
|
||||||
|
$ssh = $args['ssh'];
|
||||||
|
$agent = $args['ssh-agent'];
|
||||||
|
|
||||||
|
$hostname = $this->getEnv('SSH_HOSTNAME');
|
||||||
|
$username = $this->getEnv('SSH_USERNAME');
|
||||||
|
|
||||||
|
$this->assertEquals($username, trim($ssh->exec('whoami')));
|
||||||
|
|
||||||
|
$agent->startSSHForwarding($ssh);
|
||||||
|
$this->assertEquals($username, trim($ssh->exec("ssh " . $username . "@" . $hostname . ' \'whoami\'')));
|
||||||
|
|
||||||
|
return $args;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
123
tests/Unit/File/X509/X509Test.php
Normal file
123
tests/Unit/File/X509/X509Test.php
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2014 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once 'File/X509.php';
|
||||||
|
|
||||||
|
class Unit_File_X509_X509Test extends PhpseclibTestCase
|
||||||
|
{
|
||||||
|
public function testLoadUnsupportedExtension()
|
||||||
|
{
|
||||||
|
$test = '-----BEGIN CERTIFICATE-----
|
||||||
|
MIIG1jCCBL6gAwIBAgITUAAAAA0qg8bE6DhrLAAAAAAADTANBgkqhkiG9w0BAQsF
|
||||||
|
ADAiMSAwHgYDVQQDExcuU2VjdXJlIEVudGVycHJpc2UgQ0EgMTAeFw0xNTAyMjMx
|
||||||
|
NTE1MDdaFw0xNjAyMjMxNTE1MDdaMD8xFjAUBgoJkiaJk/IsZAEZFgZzZWN1cmUx
|
||||||
|
DjAMBgNVBAMTBVVzZXJzMRUwEwYDVQQDEwxtZXRhY2xhc3NpbmcwggEiMA0GCSqG
|
||||||
|
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMdG1CzR/gTalbLN9J+2cvMGeD7wsR7S78
|
||||||
|
HU5hdwE+kECROjRAcjFBOR57ezSDrkmhkTzo28tj0oAHjOh8N9vuXtASfZSCXugx
|
||||||
|
H+ImJ+E7PA4aXBp+0H2hohW9sXNNCFiVNmJLX66O4bxIeKtVRq/+eSNijV4OOEkC
|
||||||
|
zMyTHAUbOFP0t6KoJtM1syNoQ1+fKdfcjz5XtiEzSVcp2zf0MwNFSeZSgGQ0jh8A
|
||||||
|
Kd6YVKA8ZnrqOWZxKETT+bBNTjIT0ggjQfzcE4zW2RzrN7zWabUowoU92+DAp4s3
|
||||||
|
sAEywX9ISSge62DEzTnZZSf9bpoScAfT8raRFA3BkoJ/s4c4CgfPAgMBAAGjggLm
|
||||||
|
MIIC4jAdBgNVHQ4EFgQULlIyJL9+ZwAI/SkVdsJMxFOVp+EwHwYDVR0jBBgwFoAU
|
||||||
|
5nEIMEUT5mMd1WepmviwgK7dIzwwggEKBgNVHR8EggEBMIH+MIH7oIH4oIH1hoG5
|
||||||
|
bGRhcDovLy9DTj0uU2VjdXJlJTIwRW50ZXJwcmlzZSUyMENBJTIwMSxDTj1hdXRo
|
||||||
|
LENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxD
|
||||||
|
Tj1Db25maWd1cmF0aW9uLERDPXNlY3VyZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25M
|
||||||
|
aXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnSGN2h0dHA6
|
||||||
|
Ly9jcmwuc2VjdXJlb2JzY3VyZS5jb20vP2FjdGlvbj1jcmwmY2E9ZW50ZXJwcmlz
|
||||||
|
ZTEwgccGCCsGAQUFBwEBBIG6MIG3MIG0BggrBgEFBQcwAoaBp2xkYXA6Ly8vQ049
|
||||||
|
LlNlY3VyZSUyMEVudGVycHJpc2UlMjBDQSUyMDEsQ049QUlBLENOPVB1YmxpYyUy
|
||||||
|
MEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9
|
||||||
|
c2VjdXJlP2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0
|
||||||
|
aW9uQXV0aG9yaXR5MBcGCSsGAQQBgjcUAgQKHggAVQBzAGUAcjAOBgNVHQ8BAf8E
|
||||||
|
BAMCBaAwKQYDVR0lBCIwIAYKKwYBBAGCNwoDBAYIKwYBBQUHAwQGCCsGAQUFBwMC
|
||||||
|
MC4GA1UdEQQnMCWgIwYKKwYBBAGCNxQCA6AVDBNtZXRhY2xhc3NpbmdAc2VjdXJl
|
||||||
|
MEQGCSqGSIb3DQEJDwQ3MDUwDgYIKoZIhvcNAwICAgCAMA4GCCqGSIb3DQMEAgIA
|
||||||
|
gDAHBgUrDgMCBzAKBggqhkiG9w0DBzANBgkqhkiG9w0BAQsFAAOCAgEAKNmjYh+h
|
||||||
|
cObJEM0CWgz50jOYKZ4M5iIxoAWgrYY9Pv+0O9aPjvPLzjd5bY322L8lxh5wy5my
|
||||||
|
DKmip+irzjdVdxzQfoyy+ceODmCbX9L6MfEDn0RBzdwjLe1/eOxE1na0sZztrVCc
|
||||||
|
yt5nI91NNGZJUcVqVQsIA/25FWlkvo/FTfuqTuXdQiEVM5MCKJI915anmTdugy+G
|
||||||
|
0CmBJALIxtyz5P7sZhaHZFNdpKnx82QsauErqjP9H0RXc6VXX5qt+tEDvYfSlFcc
|
||||||
|
0lv3aQnV/eIdfm7APJkQ3lmNWWQwdkVf7adXJ7KAAPHSt1yvSbVxThJR/jmIkyeQ
|
||||||
|
XW/TOP5m7JI/GrmvdlzI1AgwJ+zO8fOmCDuif99pDb1CvkzQ65RZ8p5J1ZV6hzlb
|
||||||
|
VvOhn4LDnT1jnTcEqigmx1gxM/5ifvMorXn/ItMjKPlb72vHpeF7OeKE8GHsvZAm
|
||||||
|
osHcKyJXbTIcXchmpZX1efbmCMJBqHgJ/qBTBMl9BX0+YqbTZyabRJSs9ezbTRn0
|
||||||
|
oRYl21Q8EnvS71CemxEUkSsKJmfJKkQNCsOjc8AbX/V/X9R7LJkH3UEx6K2zQQKK
|
||||||
|
k6m17mi63YW/+iPCGOWZ2qXmY5HPEyyF2L4L4IDryFJ+8xLyw3pH9/yp5aHZDtp6
|
||||||
|
833K6qyjgHJT+fUzSEYpiwF5rSBJIGClOCY=
|
||||||
|
-----END CERTIFICATE-----';
|
||||||
|
|
||||||
|
$x509 = new File_X509();
|
||||||
|
|
||||||
|
$cert = $x509->loadX509($test);
|
||||||
|
|
||||||
|
$this->assertEquals('MDUwDgYIKoZIhvcNAwICAgCAMA4GCCqGSIb3DQMEAgIAgDAHBgUrDgMCBzAKBggqhkiG9w0DBw==', $cert['tbsCertificate']['extensions'][8]['extnValue']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSaveUnsupportedExtension()
|
||||||
|
{
|
||||||
|
$x509 = new File_X509();
|
||||||
|
$cert = $x509->loadX509('-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDITCCAoqgAwIBAgIQT52W2WawmStUwpV8tBV9TTANBgkqhkiG9w0BAQUFADBM
|
||||||
|
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
|
||||||
|
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0xMTEwMjYwMDAwMDBaFw0x
|
||||||
|
MzA5MzAyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
|
||||||
|
MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
|
||||||
|
FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
|
||||||
|
gYEA3rcmQ6aZhc04pxUJuc8PycNVjIjujI0oJyRLKl6g2Bb6YRhLz21ggNM1QDJy
|
||||||
|
wI8S2OVOj7my9tkVXlqGMaO6hqpryNlxjMzNJxMenUJdOPanrO/6YvMYgdQkRn8B
|
||||||
|
d3zGKokUmbuYOR2oGfs5AER9G5RqeC1prcB6LPrQ2iASmNMCAwEAAaOB5zCB5DAM
|
||||||
|
BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
|
||||||
|
LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
|
||||||
|
BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
|
||||||
|
Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
|
||||||
|
ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
|
||||||
|
AAOBgQAhrNWuyjSJWsKrUtKyNGadeqvu5nzVfsJcKLt0AMkQH0IT/GmKHiSgAgDp
|
||||||
|
ulvKGQSy068Bsn5fFNum21K5mvMSf3yinDtvmX3qUA12IxL/92ZzKbeVCq3Yi7Le
|
||||||
|
IOkKcGQRCMha8X2e7GmlpdWC1ycenlbN0nbVeSv3JUMcafC4+Q==
|
||||||
|
-----END CERTIFICATE-----');
|
||||||
|
|
||||||
|
$asn1 = new File_ASN1();
|
||||||
|
|
||||||
|
$value = $this->encodeOID('1.2.3.4');
|
||||||
|
$ext = chr(FILE_ASN1_TYPE_OBJECT_IDENTIFIER) . $asn1->_encodeLength(strlen($value)) . $value;
|
||||||
|
$value = 'zzzzzzzzz';
|
||||||
|
$ext.= chr(FILE_ASN1_TYPE_OCTET_STRING) . $asn1->_encodeLength(strlen($value)) . $value;
|
||||||
|
$ext = chr(FILE_ASN1_TYPE_SEQUENCE | 0x20) . $asn1->_encodeLength(strlen($ext)) . $ext;
|
||||||
|
|
||||||
|
$cert['tbsCertificate']['extensions'][4] = new File_ASN1_Element($ext);
|
||||||
|
|
||||||
|
$result = $x509->loadX509($x509->saveX509($cert));
|
||||||
|
|
||||||
|
$this->assertCount(5, $result['tbsCertificate']['extensions']);
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeOID($oid)
|
||||||
|
{
|
||||||
|
if ($oid === false) {
|
||||||
|
user_error('Invalid OID');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$value = '';
|
||||||
|
$parts = explode('.', $oid);
|
||||||
|
$value = chr(40 * $parts[0] + $parts[1]);
|
||||||
|
for ($i = 2; $i < count($parts); $i++) {
|
||||||
|
$temp = '';
|
||||||
|
if (!$parts[$i]) {
|
||||||
|
$temp = "\0";
|
||||||
|
} else {
|
||||||
|
while ($parts[$i]) {
|
||||||
|
$temp = chr(0x80 | ($parts[$i] & 0x7F)) . $temp;
|
||||||
|
$parts[$i] >>= 7;
|
||||||
|
}
|
||||||
|
$temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7F);
|
||||||
|
}
|
||||||
|
$value.= $temp;
|
||||||
|
}
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
@ -28,4 +28,6 @@ ssh-add "$HOME/.ssh/id_rsa"
|
|||||||
# Allow the private key of the travis user to log in as phpseclib user
|
# Allow the private key of the travis user to log in as phpseclib user
|
||||||
sudo mkdir -p "/home/$USERNAME/.ssh/"
|
sudo mkdir -p "/home/$USERNAME/.ssh/"
|
||||||
sudo cp "$HOME/.ssh/id_rsa.pub" "/home/$USERNAME/.ssh/authorized_keys"
|
sudo cp "$HOME/.ssh/id_rsa.pub" "/home/$USERNAME/.ssh/authorized_keys"
|
||||||
|
sudo ssh-keyscan -t rsa localhost > "/tmp/known_hosts"
|
||||||
|
sudo cp "/tmp/known_hosts" "/home/$USERNAME/.ssh/known_hosts"
|
||||||
sudo chown "$USERNAME:$USERNAME" "/home/$USERNAME/.ssh/" -R
|
sudo chown "$USERNAME:$USERNAME" "/home/$USERNAME/.ssh/" -R
|
||||||
|
Loading…
Reference in New Issue
Block a user