mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-24 11:05:30 +00:00
SSH agent forwarding implementation
This commit is contained in:
parent
10050c1748
commit
aca4ba3286
@ -99,6 +99,10 @@ 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_REQUEST', 3);
|
||||||
|
define('NET_SSH2_CHANNEL_AGENT_FORWARD', 4);
|
||||||
|
|
||||||
|
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
@ -840,6 +844,14 @@ class Net_SSH2
|
|||||||
*/
|
*/
|
||||||
var $windowRows = 24;
|
var $windowRows = 24;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario
|
||||||
|
*
|
||||||
|
* @var System_SSH_Agent
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $agent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
@ -2132,9 +2144,11 @@ 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)) {
|
||||||
|
$this->agent->_on_login_success($this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2234,6 +2248,7 @@ class Net_SSH2
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set Timeout
|
* Set Timeout
|
||||||
*
|
*
|
||||||
@ -2311,6 +2326,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');
|
||||||
@ -2341,6 +2357,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;
|
||||||
}
|
}
|
||||||
@ -2808,6 +2825,8 @@ class Net_SSH2
|
|||||||
}
|
}
|
||||||
$payload = $this->_get_binary_packet();
|
$payload = $this->_get_binary_packet();
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
|
// see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
|
||||||
@ -2830,23 +2849,6 @@ class Net_SSH2
|
|||||||
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
$payload = $this->_get_binary_packet();
|
|
||||||
break;
|
|
||||||
case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
|
|
||||||
$this->_string_shift($payload, 1);
|
|
||||||
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
|
|
||||||
$this->errors[] = 'SSH_MSG_CHANNEL_OPEN: ' . utf8_decode($this->_string_shift($payload, $length));
|
|
||||||
|
|
||||||
$this->_string_shift($payload, 4); // skip over client channel
|
|
||||||
extract(unpack('Nserver_channel', $this->_string_shift($payload, 4)));
|
|
||||||
|
|
||||||
$packet = pack('CN3a*Na*',
|
|
||||||
NET_SSH2_MSG_REQUEST_FAILURE, $server_channel, NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, 0, '', 0, '');
|
|
||||||
|
|
||||||
if (!$this->_send_binary_packet($packet)) {
|
|
||||||
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:
|
||||||
@ -2983,53 +2985,97 @@ class Net_SSH2
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Ctype/Nchannel', $this->_string_shift($response, 5)));
|
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||||
|
|
||||||
$this->window_size_server_to_client[$channel]-= strlen($response);
|
if ($type == NET_SSH2_MSG_CHANNEL_OPEN) {
|
||||||
|
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||||
// resize the window, if appropriate
|
} else {
|
||||||
if ($this->window_size_server_to_client[$channel] < 0) {
|
extract(unpack('Nchannel', $this->_string_shift($response, 4)));
|
||||||
$packet = pack('CNN', NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST, $this->server_channels[$channel], $this->window_size);
|
|
||||||
if (!$this->_send_binary_packet($packet)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$this->window_size_server_to_client[$channel]+= $this->window_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($this->channel_status[$channel]) {
|
// will not be setup yet on incoming channel open request
|
||||||
case NET_SSH2_MSG_CHANNEL_OPEN:
|
if (isset($channel) && isset($this->channel_status[$channel]) && isset($this->window_size_server_to_client[$channel])) {
|
||||||
switch ($type) {
|
$this->window_size_server_to_client[$channel]-= strlen($response);
|
||||||
case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
|
|
||||||
extract(unpack('Nserver_channel', $this->_string_shift($response, 4)));
|
// resize the window, if appropriate
|
||||||
$this->server_channels[$channel] = $server_channel;
|
if ($this->window_size_server_to_client[$channel] < 0) {
|
||||||
extract(unpack('Nwindow_size', $this->_string_shift($response, 4)));
|
$packet = pack('CNN', NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST, $this->server_channels[$channel], $this->window_size);
|
||||||
$this->window_size_client_to_server[$channel] = $window_size;
|
if (!$this->_send_binary_packet($packet)) {
|
||||||
$temp = unpack('Npacket_size_client_to_server', $this->_string_shift($response, 4));
|
return false;
|
||||||
$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);
|
|
||||||
//case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
|
|
||||||
default:
|
|
||||||
user_error('Unable to open channel');
|
|
||||||
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
|
||||||
}
|
}
|
||||||
break;
|
$this->window_size_server_to_client[$channel]+= $this->window_size;
|
||||||
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
}
|
||||||
switch ($type) {
|
|
||||||
case NET_SSH2_MSG_CHANNEL_SUCCESS:
|
switch ($this->channel_status[$channel]) {
|
||||||
return true;
|
case NET_SSH2_MSG_CHANNEL_OPEN:;
|
||||||
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
switch ($type) {
|
||||||
return false;
|
case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
|
||||||
default:
|
extract(unpack('Nserver_channel', $this->_string_shift($response, 4)));
|
||||||
user_error('Unable to fulfill channel request');
|
$this->server_channels[$channel] = $server_channel;
|
||||||
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
extract(unpack('Nwindow_size', $this->_string_shift($response, 4)));
|
||||||
}
|
$this->window_size_client_to_server[$channel] = $window_size;
|
||||||
case NET_SSH2_MSG_CHANNEL_CLOSE:
|
$temp = unpack('Npacket_size_client_to_server', $this->_string_shift($response, 4));
|
||||||
return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended);
|
$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);
|
||||||
|
//case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
|
||||||
|
default:
|
||||||
|
user_error('Unable to open channel');
|
||||||
|
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
||||||
|
switch ($type) {
|
||||||
|
case NET_SSH2_MSG_CHANNEL_SUCCESS:
|
||||||
|
return true;
|
||||||
|
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
user_error('Unable to fulfill channel request');
|
||||||
|
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||||
|
}
|
||||||
|
case NET_SSH2_MSG_CHANNEL_CLOSE:
|
||||||
|
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
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
|
case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
|
||||||
|
$data = $this->_string_shift($response, $length);
|
||||||
|
switch($data) {
|
||||||
|
case 'auth-agent':
|
||||||
|
case 'auth-agent@openssh.com':
|
||||||
|
if (!isset($this->agent)) {
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
$new_channel = NET_SSH2_CHANNEL_AGENT_FORWARD;
|
||||||
|
|
||||||
|
extract(unpack('Nserver_channel', $this->_string_shift($response, 4)));
|
||||||
|
extract(unpack('Nremote_window_size', $this->_string_shift($response, 4)));
|
||||||
|
extract(unpack('Nremote_maximum_packet_size', $this->_string_shift($response, 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;
|
||||||
case NET_SSH2_MSG_CHANNEL_DATA:
|
case NET_SSH2_MSG_CHANNEL_DATA:
|
||||||
/*
|
/*
|
||||||
if ($channel == NET_SSH2_CHANNEL_EXEC) {
|
if ($channel == NET_SSH2_CHANNEL_EXEC) {
|
||||||
@ -3042,6 +3088,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;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP ssh-agent client.
|
* Pure-PHP ssh-agent client.
|
||||||
*
|
*
|
||||||
@ -225,6 +226,29 @@ class System_SSH_Agent
|
|||||||
*/
|
*/
|
||||||
var $fsock;
|
var $fsock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Did we request agent forwarding
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $request_forwarding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 +334,133 @@ class System_SSH_Agent
|
|||||||
|
|
||||||
return $identities;
|
return $identities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request the remote server to forward authentication requests to the local SSH agent
|
||||||
|
*
|
||||||
|
* @param Net_SSH2 $ssh
|
||||||
|
* @return Boolean
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function startSSHForwarding($ssh)
|
||||||
|
{
|
||||||
|
if (!$this->request_forwarding) {
|
||||||
|
$this->request_forwarding = true;
|
||||||
|
$this->_request_forwarding($ssh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request the remote server to stop forwarding authentication requests to the local SSH agent
|
||||||
|
*
|
||||||
|
* @param Net_SSH2 $ssh
|
||||||
|
* @return Boolean
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function stopSSHForwarding($ssh)
|
||||||
|
{
|
||||||
|
if ($this->request_forwarding) {
|
||||||
|
$ssh->_close_channel(NET_SSH2_CHANNEL_AGENT_FORWARD);
|
||||||
|
$this->request_forwarding = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The worker function to make a request to a remote server
|
||||||
|
* asking it to forward authentication requests to the local SSH
|
||||||
|
* agent
|
||||||
|
*
|
||||||
|
* @param Net_SSH2 $ssh
|
||||||
|
* @return Boolean
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _request_forwarding($ssh)
|
||||||
|
{
|
||||||
|
$ssh->window_size_server_to_client[NET_SSH2_CHANNEL_AGENT_REQUEST] = $ssh->window_size;
|
||||||
|
$packet_size = 0x4000;
|
||||||
|
|
||||||
|
$packet = pack('CNa*N3',
|
||||||
|
NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SSH2_CHANNEL_AGENT_REQUEST, $ssh->window_size_server_to_client[NET_SSH2_CHANNEL_AGENT_REQUEST], $packet_size);
|
||||||
|
|
||||||
|
$ssh->channel_status[NET_SSH2_CHANNEL_AGENT_REQUEST] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||||
|
|
||||||
|
if (!$ssh->_send_binary_packet($packet)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $ssh->_get_channel_packet(NET_SSH2_CHANNEL_AGENT_REQUEST);
|
||||||
|
if ($response === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$packet = pack('CNNa*C',
|
||||||
|
NET_SSH2_MSG_CHANNEL_REQUEST, $ssh->server_channels[NET_SSH2_CHANNEL_AGENT_REQUEST], strlen('auth-agent-req@openssh.com'), 'auth-agent-req@openssh.com', 1);
|
||||||
|
|
||||||
|
$ssh->channel_status[NET_SSH2_CHANNEL_AGENT_REQUEST] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
||||||
|
|
||||||
|
if (!$ssh->_send_binary_packet($packet)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $ssh->_get_channel_packet(NET_SSH2_CHANNEL_AGENT_REQUEST);
|
||||||
|
if ($response === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On Successful Login
|
||||||
|
*
|
||||||
|
* This method should be called upon successful SSH login if you
|
||||||
|
* wish to give the SSH Agent an opportunity to take further
|
||||||
|
* action. i.e. request agent forwarding
|
||||||
|
*
|
||||||
|
* @param Net_SSH2 $ssh
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _on_login_success($ssh)
|
||||||
|
{
|
||||||
|
if ($this->request_forwarding) {
|
||||||
|
$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,27 @@ 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\'')));
|
||||||
|
$agent->stopSSHForwarding($ssh);
|
||||||
|
|
||||||
|
return $args;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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