mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-11-11 08:10:58 +00:00
SSH2: add support for multi-factor authentication
This commit is contained in:
parent
7ff96b3946
commit
ccd4ce1d19
@ -119,8 +119,9 @@ if (!class_exists('Crypt_AES')) {
|
|||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001);
|
define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001);
|
||||||
define('NET_SSH2_MASK_LOGIN', 0x00000002);
|
define('NET_SSH2_MASK_LOGIN_REQ', 0x00000002);
|
||||||
define('NET_SSH2_MASK_SHELL', 0x00000004);
|
define('NET_SSH2_MASK_LOGIN', 0x00000004);
|
||||||
|
define('NET_SSH2_MASK_SHELL', 0x00000008);
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
@ -730,10 +731,19 @@ class Net_SSH2 {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Contents of stdError
|
* Contents of stdError
|
||||||
|
*
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $stdErrorLog;
|
var $stdErrorLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Last Interactive Response
|
||||||
|
*
|
||||||
|
* @see Net_SSH2::_keyboard_interactive_process()
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $last_interactive_response = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
@ -1466,6 +1476,7 @@ class Net_SSH2 {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!($this->bitmap & NET_SSH2_MASK_LOGIN_REQ)) {
|
||||||
$packet = pack('CNa*',
|
$packet = pack('CNa*',
|
||||||
NET_SSH2_MSG_SERVICE_REQUEST, strlen('ssh-userauth'), 'ssh-userauth'
|
NET_SSH2_MSG_SERVICE_REQUEST, strlen('ssh-userauth'), 'ssh-userauth'
|
||||||
);
|
);
|
||||||
@ -1486,6 +1497,12 @@ class Net_SSH2 {
|
|||||||
user_error('Expected SSH_MSG_SERVICE_ACCEPT');
|
user_error('Expected SSH_MSG_SERVICE_ACCEPT');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$this->bitmap |= NET_SSH2_MASK_LOGIN_REQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($this->last_interactive_response)) {
|
||||||
|
return !is_string($password) ? false : $this->_keyboard_interactive_process($password);
|
||||||
|
}
|
||||||
|
|
||||||
// although PHP5's get_class() preserves the case, PHP4's does not
|
// although PHP5's get_class() preserves the case, PHP4's does not
|
||||||
if (is_object($password) && strtolower(get_class($password)) == 'crypt_rsa') {
|
if (is_object($password) && strtolower(get_class($password)) == 'crypt_rsa') {
|
||||||
@ -1559,7 +1576,10 @@ class Net_SSH2 {
|
|||||||
// multi-factor authentication
|
// multi-factor authentication
|
||||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||||
$auth_methods = explode(',', $this->_string_shift($response, $length));
|
$auth_methods = explode(',', $this->_string_shift($response, $length));
|
||||||
if (in_array('keyboard-interactive', $auth_methods)) {
|
extract(unpack('Cpartial_success', $this->_string_shift($response, 1)));
|
||||||
|
$partial_success = $partial_success != 0;
|
||||||
|
|
||||||
|
if (!$partial_success && in_array('keyboard-interactive', $auth_methods)) {
|
||||||
if ($this->_keyboard_interactive_login($username, $password)) {
|
if ($this->_keyboard_interactive_login($username, $password)) {
|
||||||
$this->bitmap |= NET_SSH2_MASK_LOGIN;
|
$this->bitmap |= NET_SSH2_MASK_LOGIN;
|
||||||
return true;
|
return true;
|
||||||
@ -1610,25 +1630,20 @@ class Net_SSH2 {
|
|||||||
{
|
{
|
||||||
$responses = func_get_args();
|
$responses = func_get_args();
|
||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
if (strlen($this->last_interactive_response)) {
|
||||||
|
$response = $this->last_interactive_response;
|
||||||
|
} else {
|
||||||
|
$orig = $response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
user_error('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case NET_SSH2_MSG_USERAUTH_INFO_REQUEST:
|
case NET_SSH2_MSG_USERAUTH_INFO_REQUEST:
|
||||||
// see http://tools.ietf.org/html/rfc4256#section-3.2
|
|
||||||
if (defined('NET_SSH2_LOGGING')) {
|
|
||||||
$this->message_number_log[count($this->message_number_log) - 1] = str_replace(
|
|
||||||
'UNKNOWN',
|
|
||||||
'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
|
|
||||||
$this->message_number_log[count($this->message_number_log) - 1]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||||
$this->_string_shift($response, $length); // name; may be empty
|
$this->_string_shift($response, $length); // name; may be empty
|
||||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||||
@ -1645,6 +1660,23 @@ class Net_SSH2 {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// see http://tools.ietf.org/html/rfc4256#section-3.2
|
||||||
|
if (strlen($this->last_interactive_response)) {
|
||||||
|
$this->last_interactive_response = '';
|
||||||
|
} else {
|
||||||
|
$this->message_number_log[count($this->message_number_log) - 1] = str_replace(
|
||||||
|
'UNKNOWN',
|
||||||
|
'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
|
||||||
|
$this->message_number_log[count($this->message_number_log) - 1]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count($responses) && $num_prompts) {
|
||||||
|
$this->last_interactive_response = $orig;
|
||||||
|
$this->bitmap |= NET_SSH_MASK_LOGIN_INTERACTIVE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
After obtaining the requested information from the user, the client
|
After obtaining the requested information from the user, the client
|
||||||
MUST respond with an SSH_MSG_USERAUTH_INFO_RESPONSE message.
|
MUST respond with an SSH_MSG_USERAUTH_INFO_RESPONSE message.
|
||||||
@ -1735,7 +1767,7 @@ class Net_SSH2 {
|
|||||||
case NET_SSH2_MSG_USERAUTH_FAILURE:
|
case NET_SSH2_MSG_USERAUTH_FAILURE:
|
||||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||||
$this->errors[] = 'SSH_MSG_USERAUTH_FAILURE: ' . $this->_string_shift($response, $length);
|
$this->errors[] = 'SSH_MSG_USERAUTH_FAILURE: ' . $this->_string_shift($response, $length);
|
||||||
return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
|
return false;
|
||||||
case NET_SSH2_MSG_USERAUTH_PK_OK:
|
case NET_SSH2_MSG_USERAUTH_PK_OK:
|
||||||
// we'll just take it on faith that the public key blob and the public key algorithm name are as
|
// we'll just take it on faith that the public key blob and the public key algorithm name are as
|
||||||
// they should be
|
// they should be
|
||||||
|
Loading…
Reference in New Issue
Block a user