summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Wininger <florian@cyberwatch.fr>2021-07-01 22:27:11 +0200
committerFlorian Wininger <florian@cyberwatch.fr>2021-07-01 22:27:11 +0200
commitda80a1f606f6985ed579126c22682ed0ce044c21 (patch)
tree0084b6bcc50c0542abc9c0e9fb33937d52880f22
parenta20286be502eaf8e44309ecffe0cc5b9e0e9ee88 (diff)
downloadnet-ssh-da80a1f606f6985ed579126c22682ed0ce044c21.tar.gz
Remove Trailing white space
-rw-r--r--.rubocop_todo.yml6
-rw-r--r--lib/net/ssh/authentication/agent.rb4
-rw-r--r--lib/net/ssh/authentication/certificate.rb2
-rw-r--r--lib/net/ssh/authentication/ed25519_loader.rb10
-rw-r--r--lib/net/ssh/authentication/methods/none.rb11
-rw-r--r--lib/net/ssh/authentication/pageant.rb173
-rw-r--r--lib/net/ssh/buffered_io.rb34
-rw-r--r--lib/net/ssh/connection/channel.rb134
-rw-r--r--lib/net/ssh/connection/event_loop.rb32
-rw-r--r--lib/net/ssh/connection/keepalive.rb20
-rw-r--r--lib/net/ssh/connection/session.rb180
-rw-r--r--lib/net/ssh/connection/term.rb113
-rw-r--r--lib/net/ssh/errors.rb20
-rw-r--r--lib/net/ssh/loggable.rb16
-rw-r--r--lib/net/ssh/prompt.rb12
-rw-r--r--lib/net/ssh/proxy/errors.rb4
-rw-r--r--lib/net/ssh/proxy/http.rb34
-rw-r--r--lib/net/ssh/proxy/https.rb12
-rw-r--r--lib/net/ssh/proxy/jump.rb14
-rw-r--r--lib/net/ssh/proxy/socks4.rb2
-rw-r--r--lib/net/ssh/proxy/socks5.rb4
-rw-r--r--lib/net/ssh/test/channel.rb40
-rw-r--r--lib/net/ssh/test/extensions.rb53
-rw-r--r--lib/net/ssh/test/kex.rb12
-rw-r--r--lib/net/ssh/test/remote_packet.rb10
-rw-r--r--lib/net/ssh/test/script.rb42
-rw-r--r--lib/net/ssh/test/socket.rb23
-rw-r--r--lib/net/ssh/transport/cipher_factory.rb22
-rw-r--r--lib/net/ssh/transport/constants.rb6
-rw-r--r--lib/net/ssh/transport/identity_cipher.rb20
-rw-r--r--lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb8
-rw-r--r--lib/net/ssh/transport/key_expander.rb13
-rw-r--r--lib/net/ssh/transport/server_version.rb26
-rw-r--r--lib/net/ssh/transport/state.rb78
-rwxr-xr-xsupport/ssh_tunnel_bug.rb6
-rw-r--r--test/authentication/methods/common.rb13
-rw-r--r--test/authentication/methods/test_keyboard_interactive.rb44
-rw-r--r--test/authentication/methods/test_none.rb16
-rw-r--r--test/authentication/methods/test_password.rb30
-rw-r--r--test/integration/mitm_server.rb2
-rw-r--r--test/integration/test_curve25519sha256.rb2
-rw-r--r--test/integration/test_ed25519_pkeys.rb18
-rw-r--r--test/integration/test_forward.rb33
-rw-r--r--test/integration/test_hmac_etm.rb2
-rw-r--r--test/start/test_transport.rb8
-rw-r--r--test/transport/hmac/test_md5.rb14
-rw-r--r--test/transport/hmac/test_md5_96.rb8
-rw-r--r--test/transport/hmac/test_none.rb12
-rw-r--r--test/transport/hmac/test_ripemd160.rb12
-rw-r--r--test/transport/hmac/test_sha1.rb12
-rw-r--r--test/transport/hmac/test_sha1_96.rb8
-rw-r--r--test/transport/hmac/test_sha2_256_96.rb8
-rw-r--r--test/transport/hmac/test_sha2_512_96.rb8
-rw-r--r--test/transport/kex/test_diffie_hellman_group14_sha1.rb2
-rw-r--r--test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb30
-rw-r--r--test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb6
-rw-r--r--test/transport/test_state.rb4
-rw-r--r--test/win_integration/test_pageant.rb8
58 files changed, 723 insertions, 773 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index e0d5c2e..30bb007 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -77,12 +77,6 @@ Layout/SpaceInsideReferenceBrackets:
Exclude:
- 'lib/net/ssh/transport/algorithms.rb'
-# Offense count: 732
-# Cop supports --auto-correct.
-# Configuration parameters: AllowInHeredoc.
-Layout/TrailingWhitespace:
- Enabled: false
-
# Offense count: 4
# Configuration parameters: AllowSafeAssignment.
Lint/AssignmentInCondition:
diff --git a/lib/net/ssh/authentication/agent.rb b/lib/net/ssh/authentication/agent.rb
index 7ff0096..f521e55 100644
--- a/lib/net/ssh/authentication/agent.rb
+++ b/lib/net/ssh/authentication/agent.rb
@@ -198,13 +198,13 @@ module Net
type, = send_and_wait(SSH2_AGENT_LOCK, :string, password)
raise AgentError, "could not lock agent" if type != SSH_AGENT_SUCCESS
end
-
+
# unlock the ssh agent with password
def unlock(password)
type, = send_and_wait(SSH2_AGENT_UNLOCK, :string, password)
raise AgentError, "could not unlock agent" if type != SSH_AGENT_SUCCESS
end
-
+
private
def unix_socket_class
diff --git a/lib/net/ssh/authentication/certificate.rb b/lib/net/ssh/authentication/certificate.rb
index 28fbe71..deeb71d 100644
--- a/lib/net/ssh/authentication/certificate.rb
+++ b/lib/net/ssh/authentication/certificate.rb
@@ -31,7 +31,7 @@ module Net
cert.key_id = buffer.read_string
cert.valid_principals = buffer.read_buffer.read_all(&:read_string)
cert.valid_after = Time.at(buffer.read_int64)
-
+
cert.valid_before = if RUBY_PLATFORM == "java"
# 0x20c49ba5e353f7 = 0x7fffffffffffffff/1000, the largest value possible for JRuby
# JRuby Time.at multiplies the arg by 1000, and then stores it in a signed long.
diff --git a/lib/net/ssh/authentication/ed25519_loader.rb b/lib/net/ssh/authentication/ed25519_loader.rb
index 08ccd94..94f87aa 100644
--- a/lib/net/ssh/authentication/ed25519_loader.rb
+++ b/lib/net/ssh/authentication/ed25519_loader.rb
@@ -1,10 +1,9 @@
-module Net
- module SSH
+module Net
+ module SSH
module Authentication
# Loads ED25519 support which requires optinal dependecies like
# ed25519, bcrypt_pbkdf
module ED25519Loader
-
begin
require 'net/ssh/authentication/ed25519'
LOADED = true
@@ -13,20 +12,19 @@ module Net
ERROR = e
LOADED = false
end
-
+
def self.raiseUnlessLoaded(message)
description = ERROR.is_a?(LoadError) ? dependenciesRequiredForED25519 : ''
description << "#{ERROR.class} : \"#{ERROR.message}\"\n" if ERROR
raise NotImplementedError, "#{message}\n#{description}" unless LOADED
end
-
+
def self.dependenciesRequiredForED25519
result = "net-ssh requires the following gems for ed25519 support:\n"
result << " * ed25519 (>= 1.2, < 2.0)\n"
result << " * bcrypt_pbkdf (>= 1.0, < 2.0)\n" unless RUBY_PLATFORM == "java"
result << "See https://github.com/net-ssh/net-ssh/issues/565 for more information\n"
end
-
end
end
end
diff --git a/lib/net/ssh/authentication/methods/none.rb b/lib/net/ssh/authentication/methods/none.rb
index c1184e1..09fdac8 100644
--- a/lib/net/ssh/authentication/methods/none.rb
+++ b/lib/net/ssh/authentication/methods/none.rb
@@ -9,24 +9,23 @@ module Net
class None < Abstract
# Attempt to authenticate as "none"
def authenticate(next_service, user="", password="")
- send_message(userauth_request(user, next_service, "none"))
+ send_message(userauth_request(user, next_service, "none"))
message = session.next_message
-
+
case message.type
when USERAUTH_SUCCESS
debug { "none succeeded" }
return true
when USERAUTH_FAILURE
debug { "none failed" }
-
+
raise Net::SSH::Authentication::DisallowedMethod unless
message[:authentications].split(/,/).include? 'none'
-
+
return false
else
raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
- end
-
+ end
end
end
end
diff --git a/lib/net/ssh/authentication/pageant.rb b/lib/net/ssh/authentication/pageant.rb
index f3de568..9c44c19 100644
--- a/lib/net/ssh/authentication/pageant.rb
+++ b/lib/net/ssh/authentication/pageant.rb
@@ -21,8 +21,8 @@ end
require 'net/ssh/errors'
-module Net
- module SSH
+module Net
+ module SSH
module Authentication
# This module encapsulates the implementation of a socket factory that
# uses the PuTTY "pageant" utility to obtain information about SSH
@@ -32,28 +32,27 @@ module Net
# by Guillaume Marçais (guillaume.marcais@free.fr). It is used and
# relicensed by permission.
module Pageant
-
# From Putty pageant.c
AGENT_MAX_MSGLEN = 8192
AGENT_COPYDATA_ID = 0x804e50ba
-
+
# The definition of the Windows methods and data structures used in
# communicating with the pageant process.
module Win # rubocop:disable Metrics/ModuleLength
# Compatibility on initialization
if RUBY_VERSION < "1.9"
extend DL::Importable
-
+
dlload 'user32.dll'
dlload 'kernel32.dll'
dlload 'advapi32.dll'
-
+
SIZEOF_DWORD = DL.sizeof('L')
elsif RUBY_VERSION < "2.1"
extend DL::Importer
dlload 'user32.dll','kernel32.dll', 'advapi32.dll'
include DL::Win32Types
-
+
SIZEOF_DWORD = DL::SIZEOF_LONG
else
extend Fiddle::Importer
@@ -61,7 +60,7 @@ module Net
include Fiddle::Win32Types
SIZEOF_DWORD = Fiddle::SIZEOF_LONG
end
-
+
if RUBY_ENGINE == "jruby"
typealias("HANDLE", "void *") # From winnt.h
typealias("PHANDLE", "void *") # From winnt.h
@@ -75,105 +74,105 @@ module Net
typealias("LPARAM", "long *") # From windef.h
typealias("PDWORD_PTR", "long *") # From basetsd.h
typealias("USHORT", "unsigned short") # From windef.h
-
+
# From winbase.h, winnt.h
INVALID_HANDLE_VALUE = -1
NULL = nil
PAGE_READWRITE = 0x0004
FILE_MAP_WRITE = 2
WM_COPYDATA = 74
-
+
SMTO_NORMAL = 0 # From winuser.h
-
+
SUFFIX = if RUBY_ENGINE == "jruby"
"A"
else
""
end
-
+
# args: lpClassName, lpWindowName
extern "HWND FindWindow#{SUFFIX}(LPCTSTR, LPCTSTR)"
-
+
# args: none
extern 'DWORD GetCurrentThreadId()'
-
+
# args: hFile, (ignored), flProtect, dwMaximumSizeHigh,
# dwMaximumSizeLow, lpName
extern "HANDLE CreateFileMapping#{SUFFIX}(HANDLE, void *, DWORD, " +
"DWORD, DWORD, LPCTSTR)"
-
+
# args: hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
# dwfileOffsetLow, dwNumberOfBytesToMap
extern 'LPVOID MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, DWORD)'
-
+
# args: lpBaseAddress
extern 'BOOL UnmapViewOfFile(LPCVOID)'
-
+
# args: hObject
extern 'BOOL CloseHandle(HANDLE)'
-
+
# args: hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult
extern "LRESULT SendMessageTimeout#{SUFFIX}(HWND, UINT, WPARAM, LPARAM, " +
"UINT, UINT, PDWORD_PTR)"
-
+
# args: none
extern 'DWORD GetLastError()'
-
+
# args: none
extern 'HANDLE GetCurrentProcess()'
-
+
# args: hProcessHandle, dwDesiredAccess, (out) phNewTokenHandle
extern 'BOOL OpenProcessToken(HANDLE, DWORD, PHANDLE)'
-
+
# args: hTokenHandle, uTokenInformationClass,
# (out) lpTokenInformation, dwTokenInformationLength
# (out) pdwInfoReturnLength
extern 'BOOL GetTokenInformation(HANDLE, UINT, LPVOID, DWORD, ' +
'PDWORD)'
-
+
# args: (out) lpSecurityDescriptor, dwRevisionLevel
extern 'BOOL InitializeSecurityDescriptor(LPVOID, DWORD)'
-
+
# args: (out) lpSecurityDescriptor, lpOwnerSid, bOwnerDefaulted
extern 'BOOL SetSecurityDescriptorOwner(LPVOID, LPVOID, BOOL)'
-
+
# args: pSecurityDescriptor
extern 'BOOL IsValidSecurityDescriptor(LPVOID)'
-
+
# Constants needed for security attribute retrieval.
# Specifies the access mask corresponding to the desired access
# rights.
TOKEN_QUERY = 0x8
-
+
# The value of TOKEN_USER from the TOKEN_INFORMATION_CLASS enum.
TOKEN_USER_INFORMATION_CLASS = 1
-
+
# The initial revision level assigned to the security descriptor.
REVISION = 1
-
+
# Structs for security attribute functions.
# Holds the retrieved user access token.
TOKEN_USER = struct ['void * SID', 'DWORD ATTRIBUTES']
-
+
# Contains the security descriptor, this gets passed to the
# function that constructs the shared memory map.
SECURITY_ATTRIBUTES = struct ['DWORD nLength',
'LPVOID lpSecurityDescriptor',
'BOOL bInheritHandle']
-
+
# The security descriptor holds security information.
SECURITY_DESCRIPTOR = struct ['UCHAR Revision', 'UCHAR Sbz1',
'USHORT Control', 'LPVOID Owner',
'LPVOID Group', 'LPVOID Sacl',
'LPVOID Dacl']
-
+
# The COPYDATASTRUCT is used to send WM_COPYDATA messages
COPYDATASTRUCT = if RUBY_ENGINE == "jruby"
struct ['ULONG_PTR dwData', 'DWORD cbData', 'LPVOID lpData']
else
struct ['uintptr_t dwData', 'DWORD cbData', 'LPVOID lpData']
end
-
+
# Compatibility for security attribute retrieval.
if RUBY_VERSION < "1.9"
# Alias functions to > 1.9 capitalization
@@ -195,15 +194,15 @@ module Net
alias_method new_name, name
module_function new_name
end
-
+
def self.malloc_ptr(size)
return DL.malloc(size)
end
-
+
def self.get_ptr(data)
return data.to_ptr
end
-
+
def self.set_ptr_data(ptr, data)
ptr[0] = data
end
@@ -219,15 +218,15 @@ module Net
attach_function :malloc, [:size_t], :pointer
attach_function :free, [:pointer], :void
end
-
+
def self.malloc_ptr(size)
Fiddle::Pointer.new(LibC.malloc(size), size, LibC.method(:free))
end
-
+
def self.get_ptr(ptr)
return data.address
end
-
+
def self.set_ptr_data(ptr, data)
ptr.write_string_length(data, data.size)
end
@@ -235,19 +234,19 @@ module Net
def self.malloc_ptr(size)
return DL::CPtr.malloc(size, DL::RUBY_FREE)
end
-
+
def self.get_ptr(data)
return DL::CPtr.to_ptr data
end
-
+
def self.set_ptr_data(ptr, data)
DL::CPtr.new(ptr)[0,data.size] = data
end
end
-
+
def self.get_security_attributes_for_user
user = get_current_user
-
+
psd_information = malloc_ptr(Win::SECURITY_DESCRIPTOR.size)
raise_error_if_zero(
Win.InitializeSecurityDescriptor(psd_information,
@@ -260,26 +259,26 @@ module Net
raise_error_if_zero(
Win.IsValidSecurityDescriptor(psd_information)
)
-
+
sa = Win::SECURITY_ATTRIBUTES.new(to_struct_ptr(malloc_ptr(Win::SECURITY_ATTRIBUTES.size)))
sa.nLength = Win::SECURITY_ATTRIBUTES.size
sa.lpSecurityDescriptor = psd_information.to_i
sa.bInheritHandle = 1
-
+
return sa
end
-
+
if RUBY_ENGINE == "jruby"
def self.ptr_to_s(ptr, size)
ret = ptr.to_s(size)
ret << "\x00" while ret.size < size
ret
end
-
+
def self.ptr_to_handle(phandle)
phandle.ptr
end
-
+
def self.ptr_to_dword(ptr)
first = ptr.ptr.to_i
second = ptr_to_s(ptr,Win::SIZEOF_DWORD).unpack('L')[0]
@@ -287,19 +286,19 @@ module Net
first
end
-
+
def self.to_token_user(ptoken_information)
TOKEN_USER.new(ptoken_information.to_ptr)
end
-
+
def self.to_struct_ptr(ptr)
ptr.to_ptr
end
-
+
def self.get_sid(user)
ptr_to_s(user.to_ptr.ptr,Win::SIZEOF_DWORD).unpack('L')[0]
end
-
+
def self.get_sid_ptr(user)
user.to_ptr.ptr
end
@@ -307,28 +306,28 @@ module Net
def self.get_sid(user)
user.SID
end
-
+
def self.ptr_to_handle(phandle)
phandle.ptr.to_i
end
-
+
def self.to_struct_ptr(ptr)
ptr
end
-
+
def self.ptr_to_dword(ptr)
ptr.to_s(Win::SIZEOF_DWORD).unpack('L')[0]
end
-
+
def self.to_token_user(ptoken_information)
TOKEN_USER.new(ptoken_information)
end
-
+
def self.get_sid_ptr(user)
user.SID
end
end
-
+
def self.get_current_user
token_handle = open_process_token(Win.GetCurrentProcess,
Win::TOKEN_QUERY)
@@ -336,10 +335,10 @@ module Net
Win::TOKEN_USER_INFORMATION_CLASS)
return token_user
end
-
+
def self.open_process_token(process_handle, desired_access)
ptoken_handle = malloc_ptr(Win::SIZEOF_DWORD)
-
+
raise_error_if_zero(
Win.OpenProcessToken(process_handle, desired_access,
ptoken_handle)
@@ -347,12 +346,12 @@ module Net
token_handle = ptr_to_handle(ptoken_handle)
return token_handle
end
-
+
def self.get_token_information(token_handle,
token_information_class)
# Hold the size of the information to be returned
preturn_length = malloc_ptr(Win::SIZEOF_DWORD)
-
+
# Going to throw an INSUFFICIENT_BUFFER_ERROR, but that is ok
# here. This is retrieving the size of the information to be
# returned.
@@ -360,7 +359,7 @@ module Net
token_information_class,
Win::NULL, 0, preturn_length)
ptoken_information = malloc_ptr(ptr_to_dword(preturn_length))
-
+
# This call is going to write the requested information to
# the memory location referenced by token_information.
raise_error_if_zero(
@@ -370,76 +369,76 @@ module Net
ptoken_information.size,
preturn_length)
)
-
+
return to_token_user(ptoken_information)
end
-
+
def self.raise_error_if_zero(result)
if result == 0
raise "Windows error: #{Win.GetLastError}"
end
end
-
+
# Get a null-terminated string given a string.
def self.get_cstr(str)
return str + "\000"
end
end
-
+
# This is the pseudo-socket implementation that mimics the interface of
# a socket, translating each request into a Windows messaging call to
# the pageant daemon. This allows pageant support to be implemented
# simply by replacing the socket factory used by the Agent class.
class Socket
private_class_method :new
-
+
# The factory method for creating a new Socket instance.
def self.open
new
end
-
+
# Create a new instance that communicates with the running pageant
# instance. If no such instance is running, this will cause an error.
def initialize
@win = Win.FindWindow("Pageant", "Pageant")
-
+
if @win.to_i == 0
raise Net::SSH::Exception,
"pageant process not running"
end
-
+
@input_buffer = Net::SSH::Buffer.new
@output_buffer = Net::SSH::Buffer.new
end
-
+
# Forwards the data to #send_query, ignoring any arguments after
# the first.
def send(data, *args)
@input_buffer.append(data)
-
+
ret = data.length
-
+
while true
return ret if @input_buffer.length < 4
msg_length = @input_buffer.read_long + 4
@input_buffer.reset!
-
+
return ret if @input_buffer.length < msg_length
msg = @input_buffer.read!(msg_length)
@output_buffer.append(send_query(msg))
end
end
-
+
# Reads +n+ bytes from the cached result of the last query. If +n+
# is +nil+, returns all remaining data from the last query.
def read(n = nil)
@output_buffer.read(n)
end
-
+
def close; end
-
+
# Packages the given query string and sends it to the pageant
# process via the Windows messaging subsystem. The result is
# cached, to be returned piece-wise when #read is called.
@@ -448,29 +447,29 @@ module Net
filemap = 0
ptr = nil
id = Win.malloc_ptr(Win::SIZEOF_DWORD)
-
+
mapname = "PageantRequest%08x" % Win.GetCurrentThreadId()
security_attributes = Win.get_ptr Win.get_security_attributes_for_user
-
+
filemap = Win.CreateFileMapping(Win::INVALID_HANDLE_VALUE,
security_attributes,
Win::PAGE_READWRITE, 0,
AGENT_MAX_MSGLEN, mapname)
-
+
if filemap == 0 || filemap == Win::INVALID_HANDLE_VALUE
raise Net::SSH::Exception,
"Creation of file mapping failed with error: #{Win.GetLastError}"
end
-
+
ptr = Win.MapViewOfFile(filemap, Win::FILE_MAP_WRITE, 0, 0,
0)
-
+
if ptr.nil? || ptr.null?
raise Net::SSH::Exception, "Mapping of file failed"
end
-
+
Win.set_ptr_data(ptr, query)
-
+
# using struct to achieve proper alignment and field size on 64-bit platform
cds = Win::COPYDATASTRUCT.new(Win.malloc_ptr(Win::COPYDATASTRUCT.size))
cds.dwData = AGENT_COPYDATA_ID
@@ -478,14 +477,14 @@ module Net
cds.lpData = Win.get_cstr(mapname)
succ = Win.SendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL,
cds.to_ptr, Win::SMTO_NORMAL, 5000, id)
-
+
if succ > 0
retlen = 4 + ptr.to_s(4).unpack("N")[0]
res = ptr.to_s(retlen)
else
raise Net::SSH::Exception, "Message failed with error: #{Win.GetLastError}"
end
-
+
return res
ensure
Win.UnmapViewOfFile(ptr) unless ptr.nil? || ptr.null?
diff --git a/lib/net/ssh/buffered_io.rb b/lib/net/ssh/buffered_io.rb
index d974a1d..464ba4c 100644
--- a/lib/net/ssh/buffered_io.rb
+++ b/lib/net/ssh/buffered_io.rb
@@ -1,7 +1,7 @@
require 'net/ssh/buffer'
require 'net/ssh/loggable'
-module Net
+module Net
module SSH
# This module is used to extend sockets and other IO objects, to allow
# them to be buffered for both read and write. This abstraction makes it
@@ -47,7 +47,7 @@ module Net
# end
module BufferedIo
include Loggable
-
+
# Called when the #extend is called on an object, with this module as the
# argument. It ensures that the modules instance variables are all properly
# initialized.
@@ -55,7 +55,7 @@ module Net
# need to use __send__ because #send is overridden in Socket
object.__send__(:initialize_buffered_io)
end
-
+
# Tries to read up to +n+ bytes of data from the remote end, and appends
# the data to the input buffer. It returns the number of bytes read, or 0
# if no data was available to be read.
@@ -69,31 +69,31 @@ module Net
@input_errors << e
return 0
end
-
+
# Read up to +length+ bytes from the input buffer. If +length+ is nil,
# all available data is read from the buffer. (See #available.)
def read_available(length=nil)
input.read(length || available)
end
-
+
# Returns the number of bytes available to be read from the input buffer.
# (See #read_available.)
def available
input.available
end
-
+
# Enqueues data in the output buffer, to be written when #send_pending
# is called. Note that the data is _not_ sent immediately by this method!
def enqueue(data)
output.append(data)
end
-
+
# Returns +true+ if there is data waiting in the output buffer, and
# +false+ otherwise.
def pending_write?
output.length > 0
end
-
+
# Sends as much of the pending output as possible. Returns +true+ if any
# data was sent, and +false+ otherwise.
def send_pending
@@ -106,7 +106,7 @@ module Net
return false
end
end
-
+
# Calls #send_pending repeatedly, if necessary, blocking until the output
# buffer is empty.
def wait_for_pending_sends
@@ -118,28 +118,28 @@ module Net
send_pending
end
end
-
+
public # these methods are primarily for use in tests
-
+
def write_buffer #:nodoc:
output.to_s
end
-
+
def read_buffer #:nodoc:
input.to_s
end
-
+
private
-
+
#--
# Can't use attr_reader here (after +private+) without incurring the
# wrath of "ruby -w". We hates it.
#++
-
+
def input; @input; end
def output; @output; end
-
+
# Initializes the intput and output buffers for this object. This method
# is called automatically when the module is mixed into an object via
# Object#extend (see Net::SSH::BufferedIo.extended), but must be called
@@ -181,7 +181,7 @@ module Net
end
end
end
-
+
def send_pending
begin
super
diff --git a/lib/net/ssh/connection/channel.rb b/lib/net/ssh/connection/channel.rb
index 835d72f..b169679 100644
--- a/lib/net/ssh/connection/channel.rb
+++ b/lib/net/ssh/connection/channel.rb
@@ -54,55 +54,55 @@ module Net
class Channel
include Loggable
include Constants
-
+
# The local id for this channel, assigned by the Net::SSH::Connection::Session instance.
attr_reader :local_id
-
+
# The remote id for this channel, assigned by the remote host.
attr_reader :remote_id
-
+
# The type of this channel, usually "session".
attr_reader :type
-
+
# The underlying Net::SSH::Connection::Session instance that supports this channel.
attr_reader :connection
-
+
# The maximum packet size that the local host can receive.
attr_reader :local_maximum_packet_size
-
+
# The maximum amount of data that the local end of this channel can
# receive. This is a total, not per-packet.
attr_reader :local_maximum_window_size
-
+
# The maximum packet size that the remote host can receive.
attr_reader :remote_maximum_packet_size
-
+
# The maximum amount of data that the remote end of this channel can
# receive. This is a total, not per-packet.
attr_reader :remote_maximum_window_size
-
+
# This is the remaining window size on the local end of this channel. When
# this reaches zero, no more data can be received.
attr_reader :local_window_size
-
+
# This is the remaining window size on the remote end of this channel. When
# this reaches zero, no more data can be sent.
attr_reader :remote_window_size
-
+
# A hash of properties for this channel. These can be used to store state
# information about this channel. See also #[] and #[]=.
attr_reader :properties
-
+
# The output buffer for this channel. Data written to the channel is
# enqueued here, to be written as CHANNEL_DATA packets during each pass of
# the event loop. See Connection::Session#process and #enqueue_pending_output.
attr_reader :output #:nodoc:
-
+
# The list of pending requests. Each time a request is sent which requires
# a reply, the corresponding callback is pushed onto this queue. As responses
# arrive, they are shifted off the front and handled.
attr_reader :pending_requests #:nodoc:
-
+
# Instantiates a new channel on the given connection, of the given type,
# and with the given id. If a block is given, it will be remembered until
# the channel is confirmed open by the server, and will be invoked at
@@ -111,36 +111,36 @@ module Net
# This also sets the default maximum packet size and maximum window size.
def initialize(connection, type, local_id, max_pkt_size = 0x8000, max_win_size = 0x20000, &on_confirm_open)
self.logger = connection.logger
-
+
@connection = connection
@type = type
@local_id = local_id
-
+
@local_maximum_packet_size = max_pkt_size
@local_window_size = @local_maximum_window_size = max_win_size
-
+
@on_confirm_open = on_confirm_open
-
+
@output = Buffer.new
-
+
@properties = {}
-
+
@pending_requests = []
@on_open_failed = @on_data = @on_extended_data = @on_process = @on_close = @on_eof = nil
@on_request = {}
@closing = @eof = @sent_eof = @local_closed = @remote_closed = false
end
-
+
# A shortcut for accessing properties of the channel (see #properties).
def [](name)
@properties[name]
end
-
+
# A shortcut for setting properties of the channel (see #properties).
def []=(name, value)
@properties[name] = value
end
-
+
# Syntactic sugar for executing a command. Sends a channel request asking
# that the given command be invoked. If the block is given, it will be
# called when the server responds. The first parameter will be the
@@ -160,7 +160,7 @@ module Net
def exec(command, &block)
send_channel_request("exec", :string, command, &block)
end
-
+
# Syntactic sugar for requesting that a subsystem be started. Subsystems
# are a way for other protocols (like SFTP) to be run, using SSH as
# the transport. Generally, you'll never need to call this directly unless
@@ -177,7 +177,7 @@ module Net
def subsystem(subsystem, &block)
send_channel_request("subsystem", :string, subsystem, &block)
end
-
+
# Syntactic sugar for setting an environment variable in the remote
# process' environment. Note that for security reasons, the server may
# refuse to set certain environment variables, or all, at the server's
@@ -189,7 +189,7 @@ module Net
def env(variable_name, variable_value, &block)
send_channel_request("env", :string, variable_name, :string, variable_value, &block)
end
-
+
# A hash of the valid PTY options (see #request_pty).
VALID_PTY_OPTIONS = { term: "xterm",
chars_wide: 80,
@@ -197,7 +197,7 @@ module Net
pixels_wide: 640,
pixels_high: 480,
modes: {} }
-
+
# Requests that a pseudo-tty (or "pty") be made available for this channel.
# This is useful when you want to invoke and interact with some kind of
# screen-based program (e.g., vim, or some menuing system).
@@ -220,21 +220,21 @@ module Net
def request_pty(opts={}, &block)
extra = opts.keys - VALID_PTY_OPTIONS.keys
raise ArgumentError, "invalid option(s) to request_pty: #{extra.inspect}" if extra.any?
-
+
opts = VALID_PTY_OPTIONS.merge(opts)
-
+
modes = opts[:modes].inject(Buffer.new) do |memo, (mode, data)|
memo.write_byte(mode).write_long(data)
end
# mark the end of the mode opcode list with a 0 byte
modes.write_byte(0)
-
+
send_channel_request("pty-req", :string, opts[:term],
:long, opts[:chars_wide], :long, opts[:chars_high],
:long, opts[:pixels_wide], :long, opts[:pixels_high],
:string, modes.to_s, &block)
end
-
+
# Sends data to the channel's remote endpoint. This usually has the
# effect of sending the given string to the remote process' stdin stream.
# Note that it does not immediately send the data across the channel,
@@ -253,7 +253,7 @@ module Net
output.append(data.to_s)
end
-
+
# Returns true if the channel exists in the channel list of the session,
# and false otherwise. This can be used to determine whether a channel has
# been closed or not.
@@ -262,7 +262,7 @@ module Net
def active?
connection.channels.key?(local_id)
end
-
+
# Runs the SSH event loop until the channel is no longer active. This is
# handy for blocking while you wait for some channel to finish.
#
@@ -271,7 +271,7 @@ module Net
def wait
connection.loop { active? }
end
-
+
# True if close() has been called; NOTE: if the channel has data waiting to
# be sent then the channel will close after all the data is sent. See
# closed?() to determine if we have actually sent CHANNEL_CLOSE to server.
@@ -280,20 +280,20 @@ module Net
def closing?
@closing
end
-
+
# True if we have sent CHANNEL_CLOSE to the remote server.
def local_closed?
@local_closed
end
-
+
def remote_closed?
@remote_closed
end
-
+
def remote_closed!
@remote_closed = true
end
-
+
# Requests that the channel be closed. It only marks the channel to be closed
# the CHANNEL_CLOSE message will be sent from event loop
def close
@@ -301,14 +301,14 @@ module Net
@closing = true
end
-
+
# Returns true if the local end of the channel has declared that no more
# data is forthcoming (see #eof!). Trying to send data via #send_data when
# this is true will result in an exception being raised.
def eof?
@eof
end
-
+
# Tells the remote end of the channel that no more data is forthcoming
# from this end of the channel. The remote end may still send data.
# The CHANNEL_EOF packet will be sent once the output buffer is empty.
@@ -317,26 +317,26 @@ module Net
@eof = true
end
-
+
# If an #on_process handler has been set up, this will cause it to be
# invoked (passing the channel itself as an argument). It also causes all
# pending output to be enqueued as CHANNEL_DATA packets (see #enqueue_pending_output).
def process
@on_process.call(self) if @on_process
enqueue_pending_output
-
+
if @eof and not @sent_eof and output.empty? and remote_id and not @local_closed
connection.send_message(Buffer.from(:byte, CHANNEL_EOF, :long, remote_id))
@sent_eof = true
end
-
+
if @closing and not @local_closed and output.empty? and remote_id
connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, remote_id))
@local_closed = true
connection.cleanup_channel(self)
end
end
-
+
# Registers a callback to be invoked when data packets are received by the
# channel. The callback is called with the channel as the first argument,
# and the data as the second.
@@ -351,7 +351,7 @@ module Net
old, @on_data = @on_data, block
old
end
-
+
# Registers a callback to be invoked when extended data packets are received
# by the channel. The callback is called with the channel as the first
# argument, the data type (as an integer) as the second, and the data as
@@ -366,7 +366,7 @@ module Net
old, @on_extended_data = @on_extended_data, block
old
end
-
+
# Registers a callback to be invoked for each pass of the event loop for
# this channel. There are no guarantees on timeliness in the event loop,
# but it will be called roughly once for each packet received by the
@@ -393,7 +393,7 @@ module Net
old, @on_process = @on_process, block
old
end
-
+
# Registers a callback to be invoked when the server acknowledges that a
# channel is closed. This is invoked with the channel as the sole argument.
#
@@ -404,7 +404,7 @@ module Net
old, @on_close = @on_close, block
old
end
-
+
# Registers a callback to be invoked when the server indicates that no more
# data will be sent to the channel (although the channel can still send
# data to the server). The channel is the sole argument to the callback.
@@ -416,7 +416,7 @@ module Net
old, @on_eof = @on_eof, block
old
end
-
+
# Registers a callback to be invoked when the server was unable to open
# the requested channel. The channel itself will be passed to the block,
# along with the integer "reason code" for the failure, and a textual
@@ -431,7 +431,7 @@ module Net
old, @on_open_failed = @on_open_failed, block
old
end
-
+
# Registers a callback to be invoked when a channel request of the given
# type is received. The callback will receive the channel as the first
# argument, and the associated (unparsed) data as the second. The data
@@ -462,7 +462,7 @@ module Net
old, @on_request[type] = @on_request[type], block
old
end
-
+
# Sends a new channel request with the given name. The extra +data+
# parameter must either be empty, or consist of an even number of
# arguments. See Net::SSH::Buffer.from for a description of their format.
@@ -495,9 +495,9 @@ module Net
connection.send_message(msg)
pending_requests << callback if callback
end
-
+
public # these methods are public, but for Net::SSH internal use only
-
+
# Enqueues pending output at the connection as CHANNEL_DATA packets. This
# does nothing if the channel has not yet been confirmed open (see
# #do_open_confirmation). This is called automatically by #process, which
@@ -505,12 +505,12 @@ module Net
# generally not need to invoke it directly.
def enqueue_pending_output #:nodoc:
return unless remote_id
-
+
while output.length > 0
length = output.length
length = remote_window_size if length > remote_window_size
length = remote_maximum_packet_size if length > remote_maximum_packet_size
-
+
if length > 0
connection.send_message(Buffer.from(:byte, CHANNEL_DATA, :long, remote_id, :string, output.read(length)))
output.consume!
@@ -520,7 +520,7 @@ module Net
end
end
end
-
+
# Invoked when the server confirms that a channel has been opened.
# The remote_id is the id of the channel as assigned by the remote host,
# and max_window and max_packet are the maximum window and maximum
@@ -536,7 +536,7 @@ module Net
set_remote_env(connection.options[:set_env]) if connection.options[:set_env]
@on_confirm_open.call(self) if @on_confirm_open
end
-
+
# Invoked when the server failed to open the channel. If an #on_open_failed
# callback was specified, it will be invoked with the channel, reason code,
# and description as arguments. Otherwise, a ChannelOpenFailed exception
@@ -548,7 +548,7 @@ module Net
raise ChannelOpenFailed.new(reason_code, description)
end
end
-
+
# Invoked when the server sends a CHANNEL_WINDOW_ADJUST packet, and
# causes the remote window size to be adjusted upwards by the given
# number of bytes. This has the effect of allowing more data to be sent
@@ -557,7 +557,7 @@ module Net
@remote_maximum_window_size += bytes
@remote_window_size += bytes
end
-
+
# Invoked when the server sends a channel request. If any #on_request
# callback has been registered for the specific type of this request,
# it is invoked. If +want_reply+ is true, a packet will be sent of
@@ -568,20 +568,20 @@ module Net
# request-specific data as the second.
def do_request(request, want_reply, data) #:nodoc:
result = true
-
+
begin
callback = @on_request[request] or raise ChannelRequestFailed
callback.call(self, data)
rescue ChannelRequestFailed
result = false
end
-
+
if want_reply
msg = Buffer.from(:byte, result ? CHANNEL_SUCCESS : CHANNEL_FAILURE, :long, remote_id)
connection.send_message(msg)
end
end
-
+
# Invokes the #on_data callback when the server sends data to the
# channel. This will reduce the available window size on the local end,
# but does not actually throttle requests that come in illegally when
@@ -591,7 +591,7 @@ module Net
update_local_window_size(data.length)
@on_data.call(self, data) if @on_data
end
-
+
# Invokes the #on_extended_data callback when the server sends
# extended data to the channel. This will reduce the available window
# size on the local end. The callback is invoked with the channel,
@@ -600,20 +600,20 @@ module Net
update_local_window_size(data.length)
@on_extended_data.call(self, type, data) if @on_extended_data
end
-
+
# Invokes the #on_eof callback when the server indicates that no
# further data is forthcoming. The callback is invoked with the channel
# as the argument.
def do_eof
@on_eof.call(self) if @on_eof
end
-
+
# Invokes the #on_close callback when the server closes a channel.
# The channel is the only argument.
def do_close
@on_close.call(self) if @on_close
end
-
+
# Invokes the next pending request callback with +false+ as the second
# argument.
def do_failure
@@ -623,7 +623,7 @@ module Net
error { "channel failure received with no pending request to handle it (bug?)" }
end
end
-
+
# Invokes the next pending request callback with +true+ as the second
# argument.
def do_success
diff --git a/lib/net/ssh/connection/event_loop.rb b/lib/net/ssh/connection/event_loop.rb
index 56085cf..869e38f 100644
--- a/lib/net/ssh/connection/event_loop.rb
+++ b/lib/net/ssh/connection/event_loop.rb
@@ -1,7 +1,7 @@
require 'net/ssh/loggable'
-module Net
- module SSH
+module Net
+ module SSH
module Connection
# EventLoop can be shared across multiple sessions
#
@@ -11,25 +11,25 @@ module Net
# and we don't pass session.
class EventLoop
include Loggable
-
+
def initialize(logger=nil)
self.logger = logger
@sessions = []
end
-
+
def register(session)
@sessions << session
end
-
+
# process until timeout
# if a block is given a session will be removed from loop
# if block returns false for that session
def process(wait = nil, &block)
return false unless ev_preprocess(&block)
-
+
ev_select_and_postprocess(wait)
end
-
+
# process the event loop but only for the sepcified session
def process_only(session, wait = nil)
orig_sessions = @sessions
@@ -42,7 +42,7 @@ module Net
@sessions = orig_sessions
end
end
-
+
# Call preprocess on each session. If block given and that
# block retuns false then we exit the processing
def ev_preprocess(&block)
@@ -53,7 +53,7 @@ module Net
return true
end
-
+
def ev_select_and_postprocess(wait)
owners = {}
r = []
@@ -67,11 +67,11 @@ module Net
sr.each { |ri| owners[ri] = session }
sw.each { |wi| owners[wi] = session }
end
-
+
readers, writers, = IO.select(r, w, nil, minwait)
-
+
fired_sessions = {}
-
+
if readers
readers.each do |reader|
session = owners[reader]
@@ -84,11 +84,11 @@ module Net
(fired_sessions[session] ||= { r: [],w: [] })[:w] << writer
end
end
-
+
fired_sessions.each do |s,rw|
s.ev_do_handle_events(rw[:r],rw[:w])
end
-
+
@sessions.each { |s| s.ev_do_postprocess(fired_sessions.key?(s)) }
true
end
@@ -106,14 +106,14 @@ module Net
return true
end
-
+
def ev_select_and_postprocess(wait)
raise "Only one session expected" unless @sessions.count == 1
session = @sessions.first
sr,sw,actwait = session.ev_do_calculate_rw_wait(wait)
readers, writers, = IO.select(sr, sw, nil, actwait)
-
+
session.ev_do_handle_events(readers,writers)
session.ev_do_postprocess(!((readers.nil? || readers.empty?) && (writers.nil? || writers.empty?)))
end
diff --git a/lib/net/ssh/connection/keepalive.rb b/lib/net/ssh/connection/keepalive.rb
index 8926ba5..cdbb3e0 100644
--- a/lib/net/ssh/connection/keepalive.rb
+++ b/lib/net/ssh/connection/keepalive.rb
@@ -1,46 +1,46 @@
require 'net/ssh/loggable'
-module Net
- module SSH
+module Net
+ module SSH
module Connection
class Keepalive
include Loggable
-
+
def initialize(session)
@last_keepalive_sent_at = nil
@unresponded_keepalive_count = 0
@session = session
self.logger = session.logger
end
-
+
def options
@session.options
end
-
+
def enabled?
options[:keepalive]
end
-
+
def interval
options[:keepalive_interval] || Session::DEFAULT_IO_SELECT_TIMEOUT
end
-
+
def should_send?
return false unless enabled?
return true unless @last_keepalive_sent_at
Time.now - @last_keepalive_sent_at >= interval
end
-
+
def keepalive_maxcount
(options[:keepalive_maxcount] || 3).to_i
end
-
+
def send_as_needed(was_events)
return if was_events
return unless should_send?
info { "sending keepalive #{@unresponded_keepalive_count}" }
-
+
@unresponded_keepalive_count += 1
@session.send_global_request("keepalive@openssh.com") { |success, response|
debug { "keepalive response successful. Missed #{@unresponded_keepalive_count - 1} keepalives" }
diff --git a/lib/net/ssh/connection/session.rb b/lib/net/ssh/connection/session.rb
index 874b23f..43546fa 100644
--- a/lib/net/ssh/connection/session.rb
+++ b/lib/net/ssh/connection/session.rb
@@ -5,8 +5,8 @@ require 'net/ssh/service/forward'
require 'net/ssh/connection/keepalive'
require 'net/ssh/connection/event_loop'
-module Net
- module SSH
+module Net
+ module SSH
module Connection
# A session class representing the connection service running on top of
# the SSH transport layer. It manages the creation of channels (see
@@ -27,50 +27,50 @@ module Net
class Session
include Loggable
include Constants
-
+
# Default IO.select timeout threshold
DEFAULT_IO_SELECT_TIMEOUT = 300
-
+
# The underlying transport layer abstraction (see Net::SSH::Transport::Session).
attr_reader :transport
-
+
# The map of options that were used to initialize this instance.
attr_reader :options
-
+
# The collection of custom properties for this instance. (See #[] and #[]=).
attr_reader :properties
-
+
# The map of channels, each key being the local-id for the channel.
attr_reader :channels #:nodoc:
-
+
# The map of listeners that the event loop knows about. See #listen_to.
attr_reader :listeners #:nodoc:
-
+
# The map of specialized handlers for opening specific channel types. See
# #on_open_channel.
attr_reader :channel_open_handlers #:nodoc:
-
+
# The list of callbacks for pending requests. See #send_global_request.
attr_reader :pending_requests #:nodoc:
-
+
class NilChannel
def initialize(session)
@session = session
end
-
+
def method_missing(sym, *args)
@session.lwarn { "ignoring request #{sym.inspect} for non-existent (closed?) channel; probably ssh server bug" }
end
end
-
+
# Create a new connection service instance atop the given transport
# layer. Initializes the listeners to be only the underlying socket object.
def initialize(transport, options={})
self.logger = transport.logger
-
+
@transport = transport
@options = options
-
+
@channel_id_counter = -1
@channels = Hash.new(NilChannel.new(self))
@listeners = { transport.socket => nil }
@@ -78,34 +78,34 @@ module Net
@channel_open_handlers = {}
@on_global_request = {}
@properties = (options[:properties] || {}).dup
-
+
@max_pkt_size = (options.key?(:max_pkt_size) ? options[:max_pkt_size] : 0x8000)
@max_win_size = (options.key?(:max_win_size) ? options[:max_win_size] : 0x20000)
-
+
@keepalive = Keepalive.new(self)
-
+
@event_loop = options[:event_loop] || SingleSessionEventLoop.new
@event_loop.register(self)
end
-
+
# Retrieves a custom property from this instance. This can be used to
# store additional state in applications that must manage multiple
# SSH connections.
def [](key)
@properties[key]
end
-
+
# Sets a custom property for this instance.
def []=(key, value)
@properties[key] = value
end
-
+
# Returns the name of the host that was given to the transport layer to
# connect to.
def host
transport.host
end
-
+
# Returns true if the underlying transport has been closed. Note that
# this can be a little misleading, since if the remote server has
# closed the connection, the local end will still think it is open
@@ -114,7 +114,7 @@ module Net
def closed?
transport.closed?
end
-
+
# Closes the session gracefully, blocking until all channels have
# successfully closed, and then closes the underlying transport layer
# connection.
@@ -128,7 +128,7 @@ module Net
end
transport.close
end
-
+
# Performs a "hard" shutdown of the connection. In general, this should
# never be done, but it might be necessary (in a rescue clause, for instance,
# when the connection needs to close but you don't know the status of the
@@ -136,10 +136,10 @@ module Net
def shutdown!
transport.shutdown!
end
-
+
# preserve a reference to Kernel#loop
alias :loop_forever :loop
-
+
# Returns +true+ if there are any channels currently active on this
# session. By default, this will not include "invisible" channels
# (such as those created by forwarding ports and such), but if you pass
@@ -156,7 +156,7 @@ module Net
channels.any? { |id, ch| !ch[:invisible] }
end
end
-
+
# The main event loop. Calls #process until #process returns false. If a
# block is given, it is passed to #process, otherwise a default proc is
# used that just returns true if there are any channels active (see #busy?).
@@ -187,7 +187,7 @@ module Net
end
end
end
-
+
# The core of the event loop. It processes a single iteration of the event
# loop. If a block is given, it should return false when the processing
# should abort, which causes #process to return false. Otherwise,
@@ -228,7 +228,7 @@ module Net
force_channel_cleanup_on_close if closed?
raise
end
-
+
# This is called internally as part of #process. It dispatches any
# available incoming packets, and then runs Net::SSH::Connection::Channel#process
# for any active channels. If a block is given, it is invoked at the
@@ -242,14 +242,14 @@ module Net
return true
end
-
+
# Called by event loop to process available data before going to
# event multiplexing
def ev_preprocess(&block)
dispatch_incoming_packets(raise_disconnect_errors: false)
each_channel { |id, channel| channel.process unless channel.local_closed? }
end
-
+
# Returns the file descriptors the event loop should wait for read/write events,
# we also return the max wait
def ev_do_calculate_rw_wait(wait)
@@ -257,12 +257,12 @@ module Net
w = r.select { |w2| w2.respond_to?(:pending_write?) && w2.pending_write? }
[r,w,io_select_wait(wait)]
end
-
+
# This is called internally as part of #process.
def postprocess(readers, writers)
ev_do_handle_events(readers, writers)
end
-
+
# It loops over the given arrays of reader IO's and writer IO's,
# processing them as needed, and
# then calls Net::SSH::Transport::Session#rekey_as_needed to allow the
@@ -278,12 +278,12 @@ module Net
end
end
end
-
+
Array(writers).each do |writer|
writer.send_pending
end
end
-
+
# calls Net::SSH::Transport::Session#rekey_as_needed to allow the
# transport layer to rekey
def ev_do_postprocess(was_events)
@@ -291,7 +291,7 @@ module Net
transport.rekey_as_needed
true
end
-
+
# Send a global request of the given type. The +extra+ parameters must
# be even in number, and conform to the same format as described for
# Net::SSH::Buffer.from. If a callback is not specified, the request will
@@ -315,7 +315,7 @@ module Net
pending_requests << callback if callback
self
end
-
+
# Requests that a new channel be opened. By default, the channel will be
# of type "session", but if you know what you're doing you can select any
# of the channel types supported by the SSH protocol. The +extra+ parameters
@@ -337,25 +337,25 @@ module Net
# channel.wait
def open_channel(type="session", *extra, &on_confirm)
local_id = get_next_channel_id
-
+
channel = Channel.new(self, type, local_id, @max_pkt_size, @max_win_size, &on_confirm)
msg = Buffer.from(:byte, CHANNEL_OPEN, :string, type, :long, local_id,
:long, channel.local_maximum_window_size,
:long, channel.local_maximum_packet_size, *extra)
send_message(msg)
-
+
channels[local_id] = channel
end
-
+
class StringWithExitstatus < String
def initialize(str, exitstatus)
super(str)
@exitstatus = exitstatus
end
-
+
attr_reader :exitstatus
end
-
+
# A convenience method for executing a command and interacting with it. If
# no block is given, all output is printed via $stdout and $stderr. Otherwise,
# the block is called for each data and extended data packet, with three
@@ -380,17 +380,17 @@ module Net
open_channel do |channel|
channel.exec(command) do |ch, success|
raise "could not execute command: #{command.inspect}" unless success
-
+
if status
channel.on_request("exit-status") do |ch2,data|
status[:exit_code] = data.read_long
end
-
+
channel.on_request("exit-signal") do |ch2, data|
status[:exit_signal] = data.read_long
end
end
-
+
channel.on_data do |ch2, data|
if block
block.call(ch2, :stdout, data)
@@ -398,7 +398,7 @@ module Net
$stdout.print(data)
end
end
-
+
channel.on_extended_data do |ch2, type, data|
if block
block.call(ch2, :stderr, data)
@@ -409,7 +409,7 @@ module Net
end
end
end
-
+
# Same as #exec, except this will block until the command finishes. Also,
# if no block is given, this will return all output (stdout and stderr)
# as a single string.
@@ -422,17 +422,17 @@ module Net
ch[:result] ||= ""
ch[:result] << data
end
-
+
status ||= {}
channel = exec(command, status: status, &block_or_concat)
channel.wait
-
+
channel[:result] ||= "" unless block
channel[:result] &&= channel[:result].force_encoding("UTF-8") unless block
-
+
StringWithExitstatus.new(channel[:result], status[:exit_code]) if channel[:result]
end
-
+
# Enqueues a message to be sent to the server as soon as the socket is
# available for writing. Most programs will never need to call this, but
# if you are implementing an extension to the SSH protocol, or if you
@@ -443,7 +443,7 @@ module Net
def send_message(message)
transport.enqueue_message(message)
end
-
+
# Adds an IO object for the event loop to listen to. If a callback
# is given, it will be invoked when the io is ready to be read, otherwise,
# the io will merely have its #fill method invoked.
@@ -481,19 +481,19 @@ module Net
def listen_to(io, &callback)
listeners[io] = callback
end
-
+
# Removes the given io object from the listeners collection, so that the
# event loop will no longer monitor it.
def stop_listening_to(io)
listeners.delete(io)
end
-
+
# Returns a reference to the Net::SSH::Service::Forward service, which can
# be used for forwarding ports over SSH.
def forward
@forward ||= Service::Forward.new(self)
end
-
+
# Registers a handler to be invoked when the server wants to open a
# channel on the client. The callback receives the connection object,
# the new channel object, and the packet itself as arguments, and should
@@ -507,7 +507,7 @@ module Net
def on_open_channel(type, &block)
channel_open_handlers[type] = block
end
-
+
# Registers a handler to be invoked when the server sends a global request
# of the given type. The callback receives the request data as the first
# parameter, and true/false as the second (indicating whether a response
@@ -518,61 +518,61 @@ module Net
old, @on_global_request[type] = @on_global_request[type], block
old
end
-
+
def cleanup_channel(channel)
if channel.local_closed? and channel.remote_closed?
info { "#{host} delete channel #{channel.local_id} which closed locally and remotely" }
channels.delete(channel.local_id)
end
end
-
+
# If the #preprocess and #postprocess callbacks for this session need to run
# periodically, this method returns the maximum number of seconds which may
# pass between callbacks.
def max_select_wait_time
@keepalive.interval if @keepalive.enabled?
end
-
+
private
-
+
# iterate channels with the posibility of callbacks opening new channels during the iteration
def each_channel(&block)
channels.dup.each(&block)
end
-
+
# Read all pending packets from the connection and dispatch them as
# appropriate. Returns as soon as there are no more pending packets.
def dispatch_incoming_packets(raise_disconnect_errors: true)
while packet = transport.poll_message
raise Net::SSH::Exception, "unexpected response #{packet.type} (#{packet.inspect})" unless MAP.key?(packet.type)
-
+
send(MAP[packet.type], packet)
end
rescue StandardError
force_channel_cleanup_on_close if closed?
raise if raise_disconnect_errors || !$!.is_a?(Net::SSH::Disconnect)
end
-
+
# Returns the next available channel id to be assigned, and increments
# the counter.
def get_next_channel_id
@channel_id_counter += 1
end
-
+
def force_channel_cleanup_on_close
channels.each do |id, channel|
channel_closed(channel)
end
end
-
+
def channel_closed(channel)
channel.remote_closed!
channel.close
-
+
cleanup_channel(channel)
channel.do_close
end
-
+
# Invoked when a global request is received. The registered global
# request callback will be invoked, if one exists, and the necessary
# reply returned.
@@ -584,41 +584,41 @@ module Net
if result != :sent && result != true && result != false
raise "expected global request handler for `#{packet[:request_type]}' to return true, false, or :sent, but got #{result.inspect}"
end
-
+
if packet[:want_reply] && result != :sent
msg = Buffer.from(:byte, result ? REQUEST_SUCCESS : REQUEST_FAILURE)
send_message(msg)
end
end
-
+
# Invokes the next pending request callback with +true+.
def request_success(packet)
info { "global request success" }
callback = pending_requests.shift
callback.call(true, packet) if callback
end
-
+
# Invokes the next pending request callback with +false+.
def request_failure(packet)
info { "global request failure" }
callback = pending_requests.shift
callback.call(false, packet) if callback
end
-
+
# Called when the server wants to open a channel. If no registered
# channel handler exists for the given channel type, CHANNEL_OPEN_FAILURE
# is returned, otherwise the callback is invoked and everything proceeds
# accordingly.
def channel_open(packet)
info { "channel open #{packet[:channel_type]}" }
-
+
local_id = get_next_channel_id
-
+
channel = Channel.new(self, packet[:channel_type], local_id, @max_pkt_size, @max_win_size)
channel.do_open_confirmation(packet[:remote_id], packet[:window_size], packet[:packet_size])
-
+
callback = channel_open_handlers[packet[:channel_type]]
-
+
if callback
begin
callback[self, channel, packet]
@@ -633,73 +633,73 @@ module Net
else
failure = [3, "unknown channel type #{channel.type}"]
end
-
+
if failure
error { failure.inspect }
msg = Buffer.from(:byte, CHANNEL_OPEN_FAILURE, :long, channel.remote_id, :long, failure[0], :string, failure[1], :string, "")
end
-
+
send_message(msg)
end
-
+
def channel_open_confirmation(packet)
info { "channel_open_confirmation: #{packet[:local_id]} #{packet[:remote_id]} #{packet[:window_size]} #{packet[:packet_size]}" }
channel = channels[packet[:local_id]]
channel.do_open_confirmation(packet[:remote_id], packet[:window_size], packet[:packet_size])
end
-
+
def channel_open_failure(packet)
error { "channel_open_failed: #{packet[:local_id]} #{packet[:reason_code]} #{packet[:description]}" }
channel = channels.delete(packet[:local_id])
channel.do_open_failed(packet[:reason_code], packet[:description])
end
-
+
def channel_window_adjust(packet)
info { "channel_window_adjust: #{packet[:local_id]} +#{packet[:extra_bytes]}" }
channels[packet[:local_id]].do_window_adjust(packet[:extra_bytes])
end
-
+
def channel_request(packet)
info { "channel_request: #{packet[:local_id]} #{packet[:request]} #{packet[:want_reply]}" }
channels[packet[:local_id]].do_request(packet[:request], packet[:want_reply], packet[:request_data])
end
-
+
def channel_data(packet)
info { "channel_data: #{packet[:local_id]} #{packet[:data].length}b" }
channels[packet[:local_id]].do_data(packet[:data])
end
-
+
def channel_extended_data(packet)
info { "channel_extended_data: #{packet[:local_id]} #{packet[:data_type]} #{packet[:data].length}b" }
channels[packet[:local_id]].do_extended_data(packet[:data_type], packet[:data])
end
-
+
def channel_eof(packet)
info { "channel_eof: #{packet[:local_id]}" }
channels[packet[:local_id]].do_eof
end
-
+
def channel_close(packet)
info { "channel_close: #{packet[:local_id]}" }
-
+
channel = channels[packet[:local_id]]
channel_closed(channel)
end
-
+
def channel_success(packet)
info { "channel_success: #{packet[:local_id]}" }
channels[packet[:local_id]].do_success
end
-
+
def channel_failure(packet)
info { "channel_failure: #{packet[:local_id]}" }
channels[packet[:local_id]].do_failure
end
-
+
def io_select_wait(wait)
[wait, max_select_wait_time].compact.min
end
-
+
MAP = Constants.constants.each_with_object({}) do |name, memo|
value = const_get(name)
next unless Integer === value
diff --git a/lib/net/ssh/connection/term.rb b/lib/net/ssh/connection/term.rb
index ef32910..d4abad1 100644
--- a/lib/net/ssh/connection/term.rb
+++ b/lib/net/ssh/connection/term.rb
@@ -1,7 +1,6 @@
-module Net
- module SSH
+module Net
+ module SSH
module Connection
-
# These constants are used when requesting a pseudo-terminal (via
# Net::SSH::Connection::Channel#request_pty). The descriptions for each are
# taken directly from RFC 4254 ("The Secure Shell (SSH) Connection Protocol"),
@@ -10,169 +9,169 @@ module Net
# Interrupt character; 255 if none. Similarly for the other characters.
# Not all of these characters are supported on all systems.
VINTR = 1
-
+
# The quit character (sends SIGQUIT signal on POSIX systems).
VQUIT = 2
-
+
# Erase the character to left of the cursor.
VERASE = 3
-
+
# Kill the current input line.
VKILL = 4
-
+
# End-of-file character (sends EOF from the terminal).
VEOF = 5
-
+
# End-of-line character in addition to carriage return and/or linefeed.
VEOL = 6
-
+
# Additional end-of-line character.
VEOL2 = 7
-
+
# Continues paused output (normally control-Q).
VSTART = 8
-
+
# Pauses output (normally control-S).
VSTOP = 9
-
+
# Suspends the current program.
VSUSP = 10
-
+
# Another suspend character.
VDSUSP = 11
-
+
# Reprints the current input line.
VREPRINT = 12
-
+
# Erases a word left of cursor.
VWERASE = 13
-
+
# Enter the next character typed literally, even if it is a special
# character.
VLNEXT = 14
-
+
# Character to flush output.
VFLUSH = 15
-
+
# Switch to a different shell layer.
VSWITCH = 16
-
+
# Prints system status line (load, command, pid, etc).
VSTATUS = 17
-
+
# Toggles the flushing of terminal output.
VDISCARD = 18
-
+
# The ignore parity flag. The parameter SHOULD be 0 if this flag is FALSE,
# and 1 if it is TRUE.
IGNPAR = 30
-
+
# Mark parity and framing errors.
PARMRK = 31
-
+
# Enable checking of parity errors.
INPCK = 32
-
+
# Strip 8th bit off characters.
ISTRIP = 33
-
+
# Map NL into CR on input.
INCLR = 34
-
+
# Ignore CR on input.
IGNCR = 35
-
+
# Map CR to NL on input.
ICRNL = 36
-
+
# Translate uppercase characters to lowercase.
IUCLC = 37
-
+
# Enable output flow control.
IXON = 38
-
+
# Any char will restart after stop.
IXANY = 39
-
+
# Enable input flow control.
IXOFF = 40
-
+
# Ring bell on input queue full.
IMAXBEL = 41
-
+
# Enable signals INTR, QUIT, [D]SUSP.
ISIG = 50
-
+
# Canonicalize input lines.
ICANON = 51
-
+
# Enable input and output of uppercase characters by preceding their
# lowercase equivalents with "\".
XCASE = 52
-
+
# Enable echoing.
ECHO = 53
-
+
# Visually erase chars.
ECHOE = 54
-
+
# Kill character discards current line.
ECHOK = 55
-
+
# Echo NL even if ECHO is off.
ECHONL = 56
-
+
# Don't flush after interrupt.
NOFLSH = 57
-
+
# Stop background jobs from output.
TOSTOP = 58
-
+
# Enable extensions.
IEXTEN = 59
-
+
# Echo control characters as ^(Char).
ECHOCTL = 60
-
+
# Visual erase for line kill.
ECHOKE = 61
-
+
# Retype pending input.
PENDIN = 62
-
+
# Enable output processing.
OPOST = 70
-
+
# Convert lowercase to uppercase.
OLCUC = 71
-
+
# Map NL to CR-NL.
ONLCR = 72
-
+
# Translate carriage return to newline (output).
OCRNL = 73
-
+
# Translate newline to carriage return-newline (output).
ONOCR = 74
-
+
# Newline performs a carriage return (output).
ONLRET = 75
-
+
# 7 bit mode.
CS7 = 90
-
+
# 8 bit mode.
CS8 = 91
-
+
# Parity enable.
PARENB = 92
-
+
# Odd parity, else even.
PARODD = 93
-
+
# Specifies the input baud rate in bits per second.
TTY_OP_ISPEED = 128
-
+
# Specifies the output baud rate in bits per second.
TTY_OP_OSPEED = 129
end
diff --git a/lib/net/ssh/errors.rb b/lib/net/ssh/errors.rb
index 8fa8a4b..c445459 100644
--- a/lib/net/ssh/errors.rb
+++ b/lib/net/ssh/errors.rb
@@ -1,4 +1,4 @@
-module Net
+module Net
module SSH
# A general exception class, to act as the ancestor of all other Net::SSH
# exception classes.
@@ -33,7 +33,7 @@ module Net
# a "channel open failed" message.
class ChannelOpenFailed < Net::SSH::Exception
attr_reader :code, :reason
-
+
def initialize(code, reason)
@code, @reason = code, reason
super "#{reason} (#{code})"
@@ -46,42 +46,42 @@ module Net
class HostKeyError < Net::SSH::Exception
# the callback to use when #remember_host! is called
attr_writer :callback #:nodoc:
-
+
# situation-specific data describing the host (see #host, #port, etc.)
attr_writer :data #:nodoc:
-
+
# An accessor for getting at the data that was used to look up the host
# (see also #fingerprint, #host, #port, #ip, and #key).
def [](key)
@data && @data[key]
end
-
+
# Returns the fingerprint of the key for the host, which either was not
# found or did not match.
def fingerprint
@data && @data[:fingerprint]
end
-
+
# Returns the host name for the remote host, as reported by the socket.
def host
@data && @data[:peer] && @data[:peer][:host]
end
-
+
# Returns the port number for the remote host, as reported by the socket.
def port
@data && @data[:peer] && @data[:peer][:port]
end
-
+
# Returns the IP address of the remote host, as reported by the socket.
def ip
@data && @data[:peer] && @data[:peer][:ip]
end
-
+
# Returns the key itself, as reported by the remote host.
def key
@data && @data[:key]
end
-
+
# Tell Net::SSH to record this host and key in the known hosts file, so
# that subsequent connections will remember them.
def remember_host!
diff --git a/lib/net/ssh/loggable.rb b/lib/net/ssh/loggable.rb
index 15ea750..49ea5dd 100644
--- a/lib/net/ssh/loggable.rb
+++ b/lib/net/ssh/loggable.rb
@@ -1,4 +1,4 @@
-module Net
+module Net
module SSH
# A simple module to make logging easier to deal with. It assumes that the
# logger instance (if not nil) quacks like a Logger object (in Ruby's
@@ -18,39 +18,39 @@ module Net
# The logger instance that will be used to log messages. If nil, nothing
# will be logged.
attr_accessor :logger
-
+
# Displays the result of yielding if the log level is Logger::DEBUG or
# greater.
def debug
logger.add(Logger::DEBUG, nil, facility) { yield } if logger && logger.debug?
end
-
+
# Displays the result of yielding if the log level is Logger::INFO or
# greater.
def info
logger.add(Logger::INFO, nil, facility) { yield } if logger && logger.info?
end
-
+
# Displays the result of yielding if the log level is Logger::WARN or
# greater. (Called lwarn to avoid shadowing with Kernel#warn.)
def lwarn
logger.add(Logger::WARN, nil, facility) { yield } if logger && logger.warn?
end
-
+
# Displays the result of yielding if the log level is Logger:ERROR or
# greater.
def error
logger.add(Logger::ERROR, nil, facility) { yield } if logger && logger.error?
end
-
+
# Displays the result of yielding if the log level is Logger::FATAL or
# greater.
def fatal
logger.add(Logger::FATAL, nil, facility) { yield } if logger && logger.fatal?
end
-
+
private
-
+
# Sets the "facility" value, used for reporting where a log message
# originates. It defaults to the name of class with the object_id
# appended.
diff --git a/lib/net/ssh/prompt.rb b/lib/net/ssh/prompt.rb
index 98715c5..e47d71e 100644
--- a/lib/net/ssh/prompt.rb
+++ b/lib/net/ssh/prompt.rb
@@ -1,6 +1,6 @@
require 'io/console'
-module Net
+module Net
module SSH
# Default prompt implementation, called for asking password from user.
# It will never be instantiated directly, but will instead be created for
@@ -23,9 +23,9 @@ module Net
def self.default(options = {})
@default ||= new(options)
end
-
+
def initialize(options = {}); end
-
+
# default prompt object implementation. More sophisticated implemenetations
# might implement caching.
class Prompter
@@ -35,7 +35,7 @@ module Net
$stdout.puts(info[:instruction]) unless info[:instruction].empty?
end
end
-
+
# ask input from user, a prompter might ask for multiple inputs
# (like user and password) in a single session.
def ask(prompt, echo=true)
@@ -45,12 +45,12 @@ module Net
$stdout.print("\n")
ret
end
-
+
# success method will be called when the password was accepted
# It's a good time to save password asked to a cache.
def success; end
end
-
+
# start password session. Multiple questions might be asked multiple times
# on the returned object. Info hash tries to uniquely identify the password
# session, so caching implementations can save passwords properly.
diff --git a/lib/net/ssh/proxy/errors.rb b/lib/net/ssh/proxy/errors.rb
index d7e5458..f696cf3 100644
--- a/lib/net/ssh/proxy/errors.rb
+++ b/lib/net/ssh/proxy/errors.rb
@@ -1,7 +1,7 @@
require 'net/ssh/errors'
-module Net
- module SSH
+module Net
+ module SSH
module Proxy
# A general exception class for all Proxy errors.
class Error < Net::SSH::Exception; end
diff --git a/lib/net/ssh/proxy/http.rb b/lib/net/ssh/proxy/http.rb
index cf94634..e7dc3d0 100644
--- a/lib/net/ssh/proxy/http.rb
+++ b/lib/net/ssh/proxy/http.rb
@@ -1,8 +1,8 @@
require 'socket'
require 'net/ssh/proxy/errors'
-module Net
- module SSH
+module Net
+ module SSH
module Proxy
# An implementation of an HTTP proxy. To use it, instantiate it, then
# pass the instantiated object via the :proxy key to Net::SSH.start:
@@ -25,14 +25,14 @@ module Net
class HTTP
# The hostname or IP address of the HTTP proxy.
attr_reader :proxy_host
-
+
# The port number of the proxy.
attr_reader :proxy_port
-
+
# The map of additional options that were given to the object at
# initialization.
attr_reader :options
-
+
# Create a new socket factory that tunnels via the given host and
# port. The +options+ parameter is a hash of additional settings that
# can be used to tweak this proxy connection. Specifically, the following
@@ -45,47 +45,47 @@ module Net
@proxy_port = proxy_port
@options = options
end
-
+
# Return a new socket connected to the given host and port via the
# proxy that was requested when the socket factory was instantiated.
def open(host, port, connection_options)
socket = establish_connection(connection_options[:timeout])
socket.write "CONNECT #{host}:#{port} HTTP/1.1\r\n"
socket.write "Host: #{host}:#{port}\r\n"
-
+
if options[:user]
credentials = ["#{options[:user]}:#{options[:password]}"].pack("m*").gsub(/\s/, "")
socket.write "Proxy-Authorization: Basic #{credentials}\r\n"
end
-
+
socket.write "\r\n"
-
+
resp = parse_response(socket)
-
+
return socket if resp[:code] == 200
-
+
socket.close
raise ConnectError, resp.inspect
end
-
+
protected
-
+
def establish_connection(connect_timeout)
Socket.tcp(proxy_host, proxy_port, nil, nil,
connect_timeout: connect_timeout)
end
-
+
def parse_response(socket)
version, code, reason = socket.gets.chomp.split(/ /, 3)
headers = {}
-
+
while (line = socket.gets) && (line.chomp! != "")
name, value = line.split(/:/, 2)
headers[name.strip] = value.strip
end
-
+
body = socket.read(headers["Content-Length"].to_i) if headers["Content-Length"]
-
+
return { version: version,
code: code.to_i,
reason: reason,
diff --git a/lib/net/ssh/proxy/https.rb b/lib/net/ssh/proxy/https.rb
index a0da2a4..4f4fdb2 100644
--- a/lib/net/ssh/proxy/https.rb
+++ b/lib/net/ssh/proxy/https.rb
@@ -3,8 +3,8 @@ require 'openssl'
require 'net/ssh/proxy/errors'
require 'net/ssh/proxy/http'
-module Net
- module SSH
+module Net
+ module SSH
module Proxy
# A specialization of the HTTP proxy which encrypts the whole connection
# using OpenSSL. This has the advantage that proxy authentication
@@ -21,9 +21,9 @@ module Net
OpenSSL::SSL::SSLContext.new
super(proxy_host, proxy_port, options)
end
-
+
protected
-
+
# Shim to make OpenSSL::SSL::SSLSocket behave like a regular TCPSocket
# for all intents and purposes of Net::SSH::BufferedIo
module SSLSocketCompatibility
@@ -31,12 +31,12 @@ module Net
object.define_singleton_method(:recv, object.method(:sysread))
object.sync_close = true
end
-
+
def send(data, _opts)
syswrite(data)
end
end
-
+
def establish_connection(connect_timeout)
plain_socket = super(connect_timeout)
OpenSSL::SSL::SSLSocket.new(plain_socket, @ssl_context).tap do |socket|
diff --git a/lib/net/ssh/proxy/jump.rb b/lib/net/ssh/proxy/jump.rb
index b92dcdc..0630bd8 100644
--- a/lib/net/ssh/proxy/jump.rb
+++ b/lib/net/ssh/proxy/jump.rb
@@ -1,8 +1,8 @@
require 'uri'
require 'net/ssh/proxy/command'
-module Net
- module SSH
+module Net
+ module SSH
module Proxy
# An implementation of a jump proxy. To use it, instantiate it,
# then pass the instantiated object via the :proxy key to
@@ -17,27 +17,27 @@ module Net
class Jump < Command
# The jump proxies
attr_reader :jump_proxies
-
+
# Create a new socket factory that tunnels via multiple jump proxes as
# [user@]host[:port].
def initialize(jump_proxies)
@jump_proxies = jump_proxies
end
-
+
# Return a new socket connected to the given host and port via the jump
# proxy that was requested when the socket factory was instantiated.
def open(host, port, connection_options = nil)
build_proxy_command_equivalent(connection_options)
super
end
-
+
# We cannot build the ProxyCommand template until we know if the :config
# option was specified during `Net::SSH.start`.
def build_proxy_command_equivalent(connection_options = nil)
first_jump, extra_jumps = jump_proxies.split(",", 2)
config = connection_options && connection_options[:config]
uri = URI.parse("ssh://#{first_jump}")
-
+
template = "ssh"
template << " -l #{uri.user}" if uri.user
template << " -p #{uri.port}" if uri.port
@@ -45,7 +45,7 @@ module Net
template << " -F #{config}" if config != true && config
template << " -W %h:%p "
template << uri.host
-
+
@command_line_template = template
end
end
diff --git a/lib/net/ssh/proxy/socks4.rb b/lib/net/ssh/proxy/socks4.rb
index ddd95b0..a964d1e 100644
--- a/lib/net/ssh/proxy/socks4.rb
+++ b/lib/net/ssh/proxy/socks4.rb
@@ -49,7 +49,7 @@ module Net
socket = Socket.tcp(proxy_host, proxy_port, nil, nil,
connect_timeout: connection_options[:timeout])
ip_addr = IPAddr.new(Resolv.getaddress(host))
-
+
packet = [VERSION, CONNECT, port.to_i, ip_addr.to_i, options[:user]].pack("CCnNZ*")
socket.send packet, 0
diff --git a/lib/net/ssh/proxy/socks5.rb b/lib/net/ssh/proxy/socks5.rb
index 77300cd..8a0ae91 100644
--- a/lib/net/ssh/proxy/socks5.rb
+++ b/lib/net/ssh/proxy/socks5.rb
@@ -93,7 +93,7 @@ module Net
packet << [port].pack("n")
socket.send packet, 0
-
+
version, reply, = socket.recv(2).unpack("C*")
socket.recv(1)
address_type = socket.recv(1).getbyte(0)
@@ -110,7 +110,7 @@ module Net
raise ConnectError, "Illegal response type"
end
portnum = socket.recv(2)
-
+
unless reply == SUCCESS
socket.close
raise ConnectError, "#{reply}"
diff --git a/lib/net/ssh/test/channel.rb b/lib/net/ssh/test/channel.rb
index 9a46ab3..3ee56e2 100644
--- a/lib/net/ssh/test/channel.rb
+++ b/lib/net/ssh/test/channel.rb
@@ -1,5 +1,5 @@
-module Net
- module SSH
+module Net
+ module SSH
module Test
# A mock channel, used for scripting actions in tests. It wraps a
# Net::SSH::Test::Script instance, and delegates to it for the most part.
@@ -18,34 +18,34 @@ module Net
class Channel
# The Net::SSH::Test::Script instance employed by this mock channel.
attr_reader :script
-
+
# Sets the local-id of this channel object (the id assigned by the client).
attr_writer :local_id
-
+
# Sets the remote-id of this channel object (the id assigned by the mock-server).
attr_writer :remote_id
-
+
# Creates a new Test::Channel instance on top of the given +script+ (which
# must be a Net::SSH::Test::Script instance).
def initialize(script)
@script = script
@local_id = @remote_id = nil
end
-
+
# Returns the local (client-assigned) id for this channel, or a Proc object
# that will return the local-id later if the local id has not yet been set.
# (See Net::SSH::Test::Packet#instantiate!.)
def local_id
@local_id || Proc.new { @local_id or raise "local-id has not been set yet!" }
end
-
+
# Returns the remote (server-assigned) id for this channel, or a Proc object
# that will return the remote-id later if the remote id has not yet been set.
# (See Net::SSH::Test::Packet#instantiate!.)
def remote_id
@remote_id || Proc.new { @remote_id or raise "remote-id has not been set yet!" }
end
-
+
# Because adjacent calls to #gets_data will sometimes cause the data packets
# to be concatenated (causing expectations in tests to fail), you may
# need to separate those calls with calls to #inject_remote_delay! (which
@@ -57,8 +57,8 @@ module Net
def inject_remote_delay!
gets_data("")
end
-
- # Scripts the sending of an "exec" channel request packet to the mock
+
+ # Scripts the sending of an "exec" channel request packet to the mock
# server. If +reply+ is true, then the server is expected to reply to the
# request, otherwise no response to this request will be sent. If +success+
# is +true+, then the request will be successful, otherwise a failure will
@@ -68,7 +68,7 @@ module Net
def sends_exec(command, reply=true, success=true)
script.sends_channel_request(self, "exec", reply, command, success)
end
-
+
# Scripts the sending of a "subsystem" channel request packet to the mock
# server. See #sends_exec for a discussion of the meaning of the +reply+
# and +success+ arguments.
@@ -77,42 +77,42 @@ module Net
def sends_subsystem(subsystem, reply=true, success=true)
script.sends_channel_request(self, "subsystem", reply, subsystem, success)
end
-
+
# Scripts the sending of a data packet across the channel.
#
# channel.sends_data "foo"
def sends_data(data)
script.sends_channel_data(self, data)
end
-
+
# Scripts the sending of an EOF packet across the channel.
#
# channel.sends_eof
def sends_eof
script.sends_channel_eof(self)
end
-
+
# Scripts the sending of a "channel close" packet across the channel.
#
# channel.sends_close
def sends_close
script.sends_channel_close(self)
end
-
+
# Scripts the sending of a "request pty" request packet across the channel.
#
# channel.sends_request_pty
def sends_request_pty
script.sends_channel_request_pty(self)
end
-
+
# Scripts the reception of a channel data packet from the remote end.
#
# channel.gets_data "bar"
def gets_data(data)
script.gets_channel_data(self, data)
end
-
+
# Scripts the reception of a channel extended data packet from the remote
# end.
#
@@ -120,21 +120,21 @@ module Net
def gets_extended_data(data)
script.gets_channel_extended_data(self, data)
end
-
+
# Scripts the reception of an "exit-status" channel request packet.
#
# channel.gets_exit_status(127)
def gets_exit_status(status=0)
script.gets_channel_request(self, "exit-status", false, status)
end
-
+
# Scripts the reception of an EOF packet from the remote end.
#
# channel.gets_eof
def gets_eof
script.gets_channel_eof(self)
end
-
+
# Scripts the reception of a "channel close" packet from the remote end.
#
# channel.gets_close
diff --git a/lib/net/ssh/test/extensions.rb b/lib/net/ssh/test/extensions.rb
index 91bb2d6..527c88b 100644
--- a/lib/net/ssh/test/extensions.rb
+++ b/lib/net/ssh/test/extensions.rb
@@ -6,15 +6,14 @@ require 'net/ssh/connection/constants'
require 'net/ssh/transport/constants'
require 'net/ssh/transport/packet_stream'
-module Net
- module SSH
+module Net
+ module SSH
module Test
# A collection of modules used to extend/override the default behavior of
# Net::SSH internals for ease of testing. As a consumer of Net::SSH, you'll
# never need to use this directly--they're all used under the covers by
# the Net::SSH::Test system.
module Extensions
-
# An extension to Net::SSH::BufferedIo (assumes that the underlying IO
# is actually a StringIO). Facilitates unit testing.
module BufferedIo
@@ -23,48 +22,48 @@ module Net
def select_for_read?
pos < size
end
-
+
# Set this to +true+ if you want the IO to pretend to be available for writing
attr_accessor :select_for_write
-
+
# Set this to +true+ if you want the IO to pretend to be in an error state
attr_accessor :select_for_error
-
+
alias select_for_write? select_for_write
alias select_for_error? select_for_error
end
-
+
# An extension to Net::SSH::Transport::PacketStream (assumes that the
# underlying IO is actually a StringIO). Facilitates unit testing.
module PacketStream
include BufferedIo # make sure we get the extensions here, too
-
+
def self.included(base) #:nodoc:
base.send :alias_method, :real_available_for_read?, :available_for_read?
base.send :alias_method, :available_for_read?, :test_available_for_read?
-
+
base.send :alias_method, :real_enqueue_packet, :enqueue_packet
base.send :alias_method, :enqueue_packet, :test_enqueue_packet
-
+
base.send :alias_method, :real_poll_next_packet, :poll_next_packet
base.send :alias_method, :poll_next_packet, :test_poll_next_packet
end
-
+
# Called when another packet should be inspected from the current
# script. If the next packet is a remote packet, it pops it off the
# script and shoves it onto this IO object, making it available to
# be read.
def idle!
return false unless script.next(:first)
-
+
if script.next(:first).remote?
self.string << script.next.to_s
self.pos = pos
end
-
+
return true
end
-
+
# The testing version of Net::SSH::Transport::PacketStream#available_for_read?.
# Returns true if there is data pending to be read. Otherwise calls #idle!.
def test_available_for_read?
@@ -73,14 +72,14 @@ module Net
idle!
false
end
-
+
# The testing version of Net::SSH::Transport::PacketStream#enqueued_packet.
# Simply calls Net::SSH::Test::Script#process on the packet.
def test_enqueue_packet(payload)
packet = Net::SSH::Buffer.new(payload.to_s)
script.process(packet)
end
-
+
# The testing version of Net::SSH::Transport::PacketStream#poll_next_packet.
# Reads the next available packet from the IO object and returns it.
def test_poll_next_packet
@@ -91,14 +90,14 @@ module Net
Net::SSH::Packet.new(read_available(length))
end
end
-
+
# An extension to Net::SSH::Connection::Channel. Facilitates unit testing.
module Channel
def self.included(base) #:nodoc:
base.send :alias_method, :send_data_for_real, :send_data
base.send :alias_method, :send_data, :send_data_for_test
end
-
+
# The testing version of Net::SSH::Connection::Channel#send_data. Calls
# the original implementation, and then immediately enqueues the data for
# output so that scripted sends are properly interpreted as discrete
@@ -108,16 +107,16 @@ module Net
enqueue_pending_output
end
end
-
+
# An extension to the built-in ::IO class. Simply redefines IO.select
# so that it can be scripted in Net::SSH unit tests.
module IO
def self.included(base) #:nodoc:
base.extend(ClassMethods)
end
-
+
@extension_enabled = false
-
+
def self.with_test_extension(&block)
orig_value = @extension_enabled
@extension_enabled = true
@@ -127,11 +126,11 @@ module Net
@extension_enabled = orig_value
end
end
-
+
def self.extension_enabled?
@extension_enabled
end
-
+
module ClassMethods
def self.extended(obj) #:nodoc:
class <<obj
@@ -139,7 +138,7 @@ module Net
alias_method :select, :select_for_test
end
end
-
+
# The testing version of ::IO.select. Assumes that all readers,
# writers, and errors arrays are either nil, or contain only objects
# that mix in Net::SSH::Test::Extensions::BufferedIo.
@@ -149,14 +148,14 @@ module Net
ready_readers = Array(readers).select { |r| r.select_for_read? }
ready_writers = Array(writers).select { |r| r.select_for_write? }
ready_errors = Array(errors).select { |r| r.select_for_error? }
-
+
return [ready_readers, ready_writers, ready_errors] if ready_readers.any? || ready_writers.any? || ready_errors.any?
-
+
processed = 0
Array(readers).each do |reader|
processed += 1 if reader.idle!
end
-
+
raise "no readers were ready for reading, and none had any incoming packets" if processed == 0 && wait != 0
[[], [], []]
diff --git a/lib/net/ssh/test/kex.rb b/lib/net/ssh/test/kex.rb
index e8a0392..9e6f5be 100644
--- a/lib/net/ssh/test/kex.rb
+++ b/lib/net/ssh/test/kex.rb
@@ -5,8 +5,8 @@ require 'net/ssh/transport/algorithms'
require 'net/ssh/transport/constants'
require 'net/ssh/transport/kex'
-module Net
- module SSH
+module Net
+ module SSH
module Test
# An implementation of a key-exchange strategy specifically for unit tests.
# (This strategy would never really work against a real SSH server--it makes
@@ -16,22 +16,22 @@ module Net
# "test" algorithm.
class Kex
include Net::SSH::Transport::Constants
-
+
# Creates a new instance of the testing key-exchange algorithm with the
# given arguments.
def initialize(algorithms, connection, data)
@connection = connection
end
-
+
# Exchange keys with the server. This returns a hash of constant values,
# and does not actually exchange keys.
def exchange_keys
result = Net::SSH::Buffer.from(:byte, NEWKEYS)
@connection.send_message(result)
-
+
buffer = @connection.next_message
raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
-
+
{ session_id: "abc-xyz",
server_key: OpenSSL::PKey::RSA.new(512),
shared_secret: OpenSSL::BN.new("1234567890", 10),
diff --git a/lib/net/ssh/test/remote_packet.rb b/lib/net/ssh/test/remote_packet.rb
index 34051f1..8f7bde2 100644
--- a/lib/net/ssh/test/remote_packet.rb
+++ b/lib/net/ssh/test/remote_packet.rb
@@ -1,8 +1,8 @@
require 'net/ssh/buffer'
require 'net/ssh/test/packet'
-module Net
- module SSH
+module Net
+ module SSH
module Test
# This is a specialization of Net::SSH::Test::Packet for representing mock
# packets that are received by the local (client) host. These are created
@@ -13,7 +13,7 @@ module Net
def remote?
true
end
-
+
# The #process method should only be called on Net::SSH::Test::LocalPacket
# packets; if it is attempted on a remote packet, then it is an expectation
# mismatch (a remote packet was received when a local packet was expected
@@ -22,8 +22,8 @@ module Net
def process(packet)
raise "received packet type #{packet.read_byte} and was not expecting any packet"
end
-
- # Returns this remote packet as a string, suitable for parsing by
+
+ # Returns this remote packet as a string, suitable for parsing by
# Net::SSH::Transport::PacketStream and friends. When a remote packet is
# received, this method is called and the result concatenated onto the
# input buffer for the packet stream.
diff --git a/lib/net/ssh/test/script.rb b/lib/net/ssh/test/script.rb
index e7cef09..7879ad7 100644
--- a/lib/net/ssh/test/script.rb
+++ b/lib/net/ssh/test/script.rb
@@ -2,8 +2,8 @@ require 'net/ssh/test/channel'
require 'net/ssh/test/local_packet'
require 'net/ssh/test/remote_packet'
-module Net
- module SSH
+module Net
+ module SSH
module Test
# Represents a sequence of scripted events that identify the behavior that
# a test expects. Methods named "sends_*" create events for packets being
@@ -21,12 +21,12 @@ module Net
# The list of scripted events. These will be Net::SSH::Test::LocalPacket
# and Net::SSH::Test::RemotePacket instances.
attr_reader :events
-
+
# Create a new, empty script.
def initialize
@events = []
end
-
+
# Scripts the opening of a channel by adding a local packet sending the
# channel open request, and if +confirm+ is true (the default), also
# adding a remote packet confirming the new channel.
@@ -36,26 +36,26 @@ module Net
def opens_channel(confirm=true)
channel = Channel.new(self)
channel.remote_id = 5555
-
+
events << LocalPacket.new(:channel_open) { |p| channel.local_id = p[:remote_id] }
-
+
events << RemotePacket.new(:channel_open_confirmation, channel.local_id, channel.remote_id, 0x20000, 0x10000) if confirm
-
+
channel
end
-
+
# A convenience method for adding an arbitrary local packet to the events
# list.
def sends(type, *args, &block)
events << LocalPacket.new(type, *args, &block)
end
-
+
# A convenience method for adding an arbitrary remote packet to the events
# list.
def gets(type, *args)
events << RemotePacket.new(type, *args)
end
-
+
# Scripts the sending of a new channel request packet to the remote host.
# +channel+ should be an instance of Net::SSH::Test::Channel. +request+
# is a string naming the request type to send, +reply+ is a boolean
@@ -84,7 +84,7 @@ module Net
end
end
end
-
+
# Scripts the sending of a channel data packet. +channel+ must be a
# Net::SSH::Test::Channel object, and +data+ is the (string) data to
# expect will be sent.
@@ -93,21 +93,21 @@ module Net
def sends_channel_data(channel, data)
events << LocalPacket.new(:channel_data, channel.remote_id, data)
end
-
+
# Scripts the sending of a channel EOF packet from the given
# Net::SSH::Test::Channel +channel+. This will typically be called via
# Net::SSH::Test::Channel#sends_eof.
def sends_channel_eof(channel)
events << LocalPacket.new(:channel_eof, channel.remote_id)
end
-
+
# Scripts the sending of a channel close packet from the given
# Net::SSH::Test::Channel +channel+. This will typically be called via
# Net::SSH::Test::Channel#sends_close.
def sends_channel_close(channel)
events << LocalPacket.new(:channel_close, channel.remote_id)
end
-
+
# Scripts the sending of a channel request pty packets from the given
# Net::SSH::Test::Channel +channel+. This will typically be called via
# Net::SSH::Test::Channel#sends_request_pty.
@@ -116,14 +116,14 @@ module Net
data += Net::SSH::Connection::Channel::VALID_PTY_OPTIONS.merge(modes: "\0").values
events << LocalPacket.new(:channel_request, channel.remote_id, *data)
end
-
+
# Scripts the reception of a channel data packet from the remote host by
# the given Net::SSH::Test::Channel +channel+. This will typically be
# called via Net::SSH::Test::Channel#gets_data.
def gets_channel_data(channel, data)
events << RemotePacket.new(:channel_data, channel.local_id, data)
end
-
+
# Scripts the reception of a channel extended data packet from the remote
# host by the given Net::SSH::Test::Channel +channel+. This will typically
# be called via Net::SSH::Test::Channel#gets_extended_data.
@@ -132,28 +132,28 @@ module Net
def gets_channel_extended_data(channel, data)
events << RemotePacket.new(:channel_extended_data, channel.local_id, 1, data)
end
-
+
# Scripts the reception of a channel request packet from the remote host by
# the given Net::SSH::Test::Channel +channel+. This will typically be
# called via Net::SSH::Test::Channel#gets_exit_status.
def gets_channel_request(channel, request, reply, data)
events << RemotePacket.new(:channel_request, channel.local_id, request, reply, data)
end
-
+
# Scripts the reception of a channel EOF packet from the remote host by
# the given Net::SSH::Test::Channel +channel+. This will typically be
# called via Net::SSH::Test::Channel#gets_eof.
def gets_channel_eof(channel)
events << RemotePacket.new(:channel_eof, channel.local_id)
end
-
+
# Scripts the reception of a channel close packet from the remote host by
# the given Net::SSH::Test::Channel +channel+. This will typically be
# called via Net::SSH::Test::Channel#gets_close.
def gets_channel_close(channel)
events << RemotePacket.new(:channel_close, channel.local_id)
end
-
+
# By default, removes the next event in the list and returns it. However,
# this can also be used to non-destructively peek at the next event in the
# list, by passing :first as the argument.
@@ -166,7 +166,7 @@ module Net
def next(mode=:shift)
events.send(mode)
end
-
+
# Compare the given packet against the next event in the list. If there is
# no next event, an exception will be raised. This is called by
# Net::SSH::Test::Extensions::PacketStream#test_enqueue_packet.
diff --git a/lib/net/ssh/test/socket.rb b/lib/net/ssh/test/socket.rb
index c5e781f..42ece27 100644
--- a/lib/net/ssh/test/socket.rb
+++ b/lib/net/ssh/test/socket.rb
@@ -3,63 +3,62 @@ require 'stringio'
require 'net/ssh/test/extensions'
require 'net/ssh/test/script'
-module Net
- module SSH
+module Net
+ module SSH
module Test
# A mock socket implementation for use in testing. It implements the minimum
# necessary interface for interacting with the rest of the Net::SSH::Test
# system.
class Socket < StringIO
attr_reader :host, :port
-
+
# The Net::SSH::Test::Script object in use by this socket. This is the
# canonical script instance that should be used for any test depending on
# this socket instance.
attr_reader :script
-
+
# Create a new test socket. This will also instantiate a new Net::SSH::Test::Script
# and seed it with the necessary events to power the initialization of the
# connection.
def initialize
extend(Net::SSH::Transport::PacketStream)
super "SSH-2.0-Test\r\n"
-
+
@script = Script.new
-
+
script.sends(:kexinit)
script.gets(:kexinit, 1, 2, 3, 4, "test", "ssh-rsa", "none", "none", "none", "none", "none", "none", "", "", false)
script.sends(:newkeys)
script.gets(:newkeys)
end
-
+
# This doesn't actually do anything, since we don't really care what gets
# written.
def write(data)
# black hole, because we don't actually care about what gets written
end
-
+
# Allows the socket to also mimic a socket factory, simply returning
# +self+.
def open(host, port, options={})
@host, @port = host, port
self
end
-
+
# Returns a sockaddr struct for the port and host that were used when the
# socket was instantiated.
def getpeername
::Socket.sockaddr_in(port, host)
end
-
+
# Alias to #read, but never returns nil (returns an empty string instead).
def recv(n)
read(n) || ""
end
-
+
def readpartial(n)
recv(n)
end
-
end
end
end
diff --git a/lib/net/ssh/transport/cipher_factory.rb b/lib/net/ssh/transport/cipher_factory.rb
index da3317f..bedf1ea 100644
--- a/lib/net/ssh/transport/cipher_factory.rb
+++ b/lib/net/ssh/transport/cipher_factory.rb
@@ -3,8 +3,8 @@ require 'net/ssh/transport/ctr.rb'
require 'net/ssh/transport/key_expander'
require 'net/ssh/transport/identity_cipher'
-module Net
- module SSH
+module Net
+ module SSH
module Transport
# Implements a factory of OpenSSL cipher algorithms.
class CipherFactory
@@ -37,7 +37,7 @@ module Net
return OpenSSL::Cipher.ciphers.include?(ossl_name)
end
-
+
# Retrieves a new instance of the named algorithm. The new instance
# will be initialized using an iv and key generated from the given
# iv, key, shared, hash and digester values. Additionally, the
@@ -48,11 +48,11 @@ module Net
return IdentityCipher if ossl_name == "none"
cipher = OpenSSL::Cipher.new(ossl_name)
-
+
cipher.send(options[:encrypt] ? :encrypt : :decrypt)
-
+
cipher.padding = 0
-
+
if name =~ /-ctr(@openssh.org)?$/
if ossl_name !~ /-ctr/
cipher.extend(Net::SSH::Transport::CTR)
@@ -61,14 +61,14 @@ module Net
end
end
cipher.iv = Net::SSH::Transport::KeyExpander.expand_key(cipher.iv_len, options[:iv], options)
-
+
key_len = cipher.key_len
cipher.key_len = key_len
cipher.key = Net::SSH::Transport::KeyExpander.expand_key(key_len, options[:key], options)
-
+
return cipher
end
-
+
# Returns a two-element array containing the [ key-length,
# block-size ] for the named cipher algorithm. If the cipher
# algorithm is unknown, or is "none", 0 is returned for both elements
@@ -83,7 +83,7 @@ module Net
cipher = OpenSSL::Cipher.new(ossl_name)
key_len = cipher.key_len
cipher.key_len = key_len
-
+
block_size =
case ossl_name
when /\-ctr/
@@ -91,7 +91,7 @@ module Net
else
cipher.block_size
end
-
+
result = [key_len, block_size]
result << cipher.iv_len if options[:iv_len]
end
diff --git a/lib/net/ssh/transport/constants.rb b/lib/net/ssh/transport/constants.rb
index 26747a6..b3c5fb4 100644
--- a/lib/net/ssh/transport/constants.rb
+++ b/lib/net/ssh/transport/constants.rb
@@ -1,5 +1,5 @@
-module Net
- module SSH
+module Net
+ module SSH
module Transport
module Constants
#--
@@ -12,7 +12,7 @@ module Net
DEBUG = 4
SERVICE_REQUEST = 5
SERVICE_ACCEPT = 6
-
+
#--
# Algorithm negotiation messages
#++
diff --git a/lib/net/ssh/transport/identity_cipher.rb b/lib/net/ssh/transport/identity_cipher.rb
index a23c85c..b8a90bc 100644
--- a/lib/net/ssh/transport/identity_cipher.rb
+++ b/lib/net/ssh/transport/identity_cipher.rb
@@ -1,5 +1,5 @@
-module Net
- module SSH
+module Net
+ module SSH
module Transport
# A cipher that does nothing but pass the data through, unchanged. This
# keeps things in the code nice and clean when a cipher has not yet been
@@ -10,42 +10,42 @@ module Net
def block_size
8
end
-
+
# Returns an arbitrary integer.
def iv_len
4
end
-
+
# Does nothing. Returns self.
def encrypt
self
end
-
+
# Does nothing. Returns self.
def decrypt
self
end
-
+
# Passes its single argument through unchanged.
def update(text)
text
end
-
+
# Returns the empty string.
def final
""
end
-
+
# The name of this cipher, which is "identity".
def name
"identity"
end
-
+
# Does nothing. Returns nil.
def iv=(v)
nil
end
-
+
# Does nothing. Returns self.
def reset
self
diff --git a/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb b/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb
index d560da8..d74c521 100644
--- a/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb
+++ b/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb
@@ -1,8 +1,8 @@
require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
-module Net
- module SSH
- module Transport
+module Net
+ module SSH
+ module Transport
module Kex
# A key-exchange service implementing the "diffie-hellman-group14-sha1"
# key-exchange algorithm. (defined in RFC 4253)
@@ -24,7 +24,7 @@ module Net
"B5C55DF0" "6F4C52C9" "DE2BCBF6" "95581718" +
"3995497C" "EA956AE5" "15D22618" "98FA0510" +
"15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"
-
+
# The radix in which P_s represents the value of P
P_r = 16
diff --git a/lib/net/ssh/transport/key_expander.rb b/lib/net/ssh/transport/key_expander.rb
index 108e9b9..93fbaf1 100644
--- a/lib/net/ssh/transport/key_expander.rb
+++ b/lib/net/ssh/transport/key_expander.rb
@@ -1,28 +1,27 @@
-module Net
- module SSH
+module Net
+ module SSH
module Transport
module KeyExpander
-
# Generate a key value in accordance with the SSH2 specification.
# (RFC4253 7.2. "Output from Key Exchange")
def self.expand_key(bytes, start, options={})
if bytes == 0
return ""
end
-
+
k = start[0, bytes]
return k if k.length >= bytes
-
+
digester = options[:digester] or raise 'No digester supplied'
shared = options[:shared] or raise 'No shared secret supplied'
hash = options[:hash] or raise 'No hash supplied'
-
+
while k.length < bytes
step = digester.digest(shared + hash + k)
bytes_needed = bytes - k.length
k << step[0, bytes_needed]
end
-
+
return k
end
end
diff --git a/lib/net/ssh/transport/server_version.rb b/lib/net/ssh/transport/server_version.rb
index ba37beb..82de8b0 100644
--- a/lib/net/ssh/transport/server_version.rb
+++ b/lib/net/ssh/transport/server_version.rb
@@ -2,8 +2,8 @@ require 'net/ssh/errors'
require 'net/ssh/loggable'
require 'net/ssh/version'
-module Net
- module SSH
+module Net
+ module SSH
module Transport
# Negotiates the SSH protocol version and trades information about server
# and client. This is never used directly--it is always called by the
@@ -14,16 +14,16 @@ module Net
# the authoritative reference for any queries regarding the version in effect.
class ServerVersion
include Loggable
-
+
# The SSH version string as reported by Net::SSH
PROTO_VERSION = "SSH-2.0-Ruby/Net::SSH_#{Net::SSH::Version::CURRENT} #{RUBY_PLATFORM}"
-
+
# Any header text sent by the server prior to sending the version.
attr_reader :header
-
+
# The version string reported by the server.
attr_reader :version
-
+
# Instantiates a new ServerVersion and immediately (and synchronously)
# negotiates the SSH protocol in effect, using the given socket.
def initialize(socket, logger, timeout = nil)
@@ -32,19 +32,19 @@ module Net
@logger = logger
negotiate!(socket, timeout)
end
-
+
private
-
+
# Negotiates the SSH protocol to use, via the given socket. If the server
# reports an incompatible SSH version (e.g., SSH1), this will raise an
# exception.
def negotiate!(socket, timeout)
info { "negotiating protocol version" }
-
+
debug { "local is `#{PROTO_VERSION}'" }
socket.write "#{PROTO_VERSION}\r\n"
socket.flush
-
+
raise Net::SSH::ConnectionTimeout, "timeout during server version negotiating" if timeout && !IO.select([socket], nil, nil, timeout)
loop do
@@ -63,12 +63,12 @@ module Net
@header << @version
end
-
+
@version.chomp!
debug { "remote is `#{@version}'" }
-
+
raise Net::SSH::Exception, "incompatible SSH version `#{@version}'" unless @version.match(/^SSH-(1\.99|2\.0)-/)
-
+
raise Net::SSH::ConnectionTimeout, "timeout during client version negotiating" if timeout && !IO.select(nil, [socket], nil, timeout)
end
end
diff --git a/lib/net/ssh/transport/state.rb b/lib/net/ssh/transport/state.rb
index 0eaa78a..8f5fd8f 100644
--- a/lib/net/ssh/transport/state.rb
+++ b/lib/net/ssh/transport/state.rb
@@ -2,8 +2,8 @@ require 'zlib'
require 'net/ssh/transport/cipher_factory'
require 'net/ssh/transport/hmac'
-module Net
- module SSH
+module Net
+ module SSH
module Transport
# Encapsulates state information about one end of an SSH connection. Such
# state includes the packet sequence number, the algorithms in use, how
@@ -13,46 +13,46 @@ module Net
class State
# The socket object that owns this state object.
attr_reader :socket
-
+
# The next packet sequence number for this socket endpoint.
attr_reader :sequence_number
-
+
# The hmac algorithm in use for this endpoint.
attr_reader :hmac
-
+
# The compression algorithm in use for this endpoint.
attr_reader :compression
-
+
# The compression level to use when compressing data (or nil, for the default).
attr_reader :compression_level
-
+
# The number of packets processed since the last call to #reset!
attr_reader :packets
-
+
# The number of data blocks processed since the last call to #reset!
attr_reader :blocks
-
+
# The cipher algorithm in use for this socket endpoint.
attr_reader :cipher
-
+
# The block size for the cipher
attr_reader :block_size
-
+
# The role that this state plays (either :client or :server)
attr_reader :role
-
+
# The maximum number of packets that this endpoint wants to process before
# needing a rekey.
attr_accessor :max_packets
-
+
# The maximum number of blocks that this endpoint wants to process before
# needing a rekey.
attr_accessor :max_blocks
-
+
# The user-specified maximum number of bytes that this endpoint ought to
# process before needing a rekey.
attr_accessor :rekey_limit
-
+
# Creates a new state object, belonging to the given socket. Initializes
# the algorithms to "none".
def initialize(socket, role)
@@ -66,7 +66,7 @@ module Net
@compressor = @decompressor = nil
@next_iv = ""
end
-
+
# A convenience method for quickly setting multiple values in a single
# command.
def set(values)
@@ -75,19 +75,19 @@ module Net
end
reset!
end
-
+
def update_cipher(data)
result = cipher.update(data)
update_next_iv(role == :client ? result : data)
return result
end
-
+
def final_cipher
result = cipher.final
update_next_iv(role == :client ? result : "", true)
return result
end
-
+
# Increments the counters. The sequence number is incremented (and remapped
# so it always fits in a 32-bit integer). The number of packets and blocks
# are also incremented.
@@ -96,18 +96,18 @@ module Net
@packets += 1
@blocks += (packet_length + 4) / @block_size
end
-
+
# The compressor object to use when compressing data. This takes into account
# the desired compression level.
def compressor
@compressor ||= Zlib::Deflate.new(compression_level || Zlib::DEFAULT_COMPRESSION)
end
-
+
# The decompressor object to use when decompressing data.
def decompressor
@decompressor ||= Zlib::Inflate.new(nil)
end
-
+
# Returns true if data compression/decompression is enabled. This will
# return true if :standard compression is selected, or if :delayed
# compression is selected and the :authenticated hint has been received
@@ -115,7 +115,7 @@ module Net
def compression?
compression == :standard || (compression == :delayed && socket.hints[:authenticated])
end
-
+
# Compresses the data. If no compression is in effect, this will just return
# the data unmodified, otherwise it uses #compressor to compress the data.
def compress(data)
@@ -124,7 +124,7 @@ module Net
compressor.deflate(data, Zlib::SYNC_FLUSH)
end
-
+
# Deompresses the data. If no compression is in effect, this will just return
# the data unmodified, otherwise it uses #decompressor to decompress the data.
def decompress(data)
@@ -133,17 +133,17 @@ module Net
decompressor.inflate(data)
end
-
+
# Resets the counters on the state object, but leaves the sequence_number
# unchanged. It also sets defaults for and recomputes the max_packets and
# max_blocks values.
def reset!
@packets = @blocks = 0
-
+
@max_packets ||= 1 << 31
-
+
@block_size = cipher.block_size
-
+
if max_blocks.nil?
# cargo-culted from openssh. the idea is that "the 2^(blocksize*2)
# limit is too expensive for 3DES, blowfish, etc., so enforce a 1GB
@@ -153,16 +153,16 @@ module Net
else
@max_blocks = (1 << 30) / @block_size
end
-
+
# if a limit on the # of bytes has been given, convert that into a
# minimum number of blocks processed.
-
+
@max_blocks = [@max_blocks, rekey_limit / @block_size].min if rekey_limit
end
-
+
cleanup
end
-
+
# Closes any the compressor and/or decompressor objects that have been
# instantiated.
def cleanup
@@ -170,17 +170,17 @@ module Net
@compressor.finish if !@compressor.finished?
@compressor.close
end
-
+
if @decompressor
# we call reset here so that we don't get warnings when we try to
# close the decompressor
@decompressor.reset
@decompressor.close
end
-
+
@compressor = @decompressor = nil
end
-
+
# Returns true if the number of packets processed exceeds the maximum
# number of packets, or if the number of blocks processed exceeds the
# maximum number of blocks.
@@ -188,18 +188,18 @@ module Net
max_packets && packets > max_packets ||
max_blocks && blocks > max_blocks
end
-
+
private
-
+
def update_next_iv(data, reset=false)
@next_iv << data
@next_iv = @next_iv[@next_iv.size - cipher.iv_len..-1]
-
+
if reset
cipher.reset
cipher.iv = @next_iv
end
-
+
return data
end
end
diff --git a/support/ssh_tunnel_bug.rb b/support/ssh_tunnel_bug.rb
index d5fa09d..3f8f0ba 100755
--- a/support/ssh_tunnel_bug.rb
+++ b/support/ssh_tunnel_bug.rb
@@ -15,12 +15,12 @@
# visible_hostname netsshtest
# * Start squid squid -N -d 1 -D
# * Run this script
-# * Configure browser proxy to use localhost with LOCAL_PORT.
+# * Configure browser proxy to use localhost with LOCAL_PORT.
# * Load any page, wait for it to load fully. If the page loads
# correctly, move on. If not, something needs to be corrected.
# * Refresh the page several times. This should cause this
# script to failed with the error: "closed stream". You may
-# need to try a few times.
+# need to try a few times.
#
require 'highline/import'
@@ -37,7 +37,7 @@ pass = ask("Password: ") { |q| q.echo = "*" }
puts "Configure your browser proxy to localhost:#{LOCAL_PORT}"
begin
- session = Net::SSH.start(host, user, password: pass)
+ session = Net::SSH.start(host, user, password: pass)
session.forward.local(LOCAL_PORT, host, PROXY_PORT)
session.loop {true}
rescue StandardError => e
diff --git a/test/authentication/methods/common.rb b/test/authentication/methods/common.rb
index 5546e1c..be9c11a 100644
--- a/test/authentication/methods/common.rb
+++ b/test/authentication/methods/common.rb
@@ -1,18 +1,18 @@
-module Authentication
+module Authentication
module Methods
module Common
include Net::SSH::Authentication::Constants
-
+
private
-
+
def socket(options={})
@socket ||= stub("socket", client_name: "me.ssh.test")
end
-
+
def transport(options={})
@transport ||= MockTransport.new(options.merge(socket: socket))
end
-
+
def session(options={})
@session ||= begin
sess = stub("auth-session", logger: nil, transport: transport(options))
@@ -22,13 +22,12 @@ module Authentication
sess
end
end
-
+
def reset_session(options = {})
@transport = nil
@session = nil
session(options)
end
-
end
end
end
diff --git a/test/authentication/methods/test_keyboard_interactive.rb b/test/authentication/methods/test_keyboard_interactive.rb
index e18f02c..76d5272 100644
--- a/test/authentication/methods/test_keyboard_interactive.rb
+++ b/test/authentication/methods/test_keyboard_interactive.rb
@@ -2,18 +2,18 @@ require_relative '../../common'
require 'net/ssh/authentication/methods/keyboard_interactive'
require_relative 'common'
-module Authentication
+module Authentication
module Methods
class TestKeyboardInteractive < NetSSHTest
include Common
-
+
USERAUTH_INFO_REQUEST = 60
USERAUTH_INFO_RESPONSE = 61
-
+
def setup
reset_subject({}) if defined? @subject && !@subject.options.empty?
end
-
+
def test_authenticate_should_raise_if_keyboard_interactive_disallowed
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
@@ -22,18 +22,18 @@ module Authentication
assert_equal "keyboard-interactive", packet.read_string
assert_equal "", packet.read_string # language tags
assert_equal "", packet.read_string # submethods
-
+
t.return(USERAUTH_FAILURE, :string, "password")
end
-
+
assert_raises Net::SSH::Authentication::DisallowedMethod do
subject.authenticate("ssh-connection", "jamis")
end
end
-
+
def test_authenticate_should_be_false_if_given_password_is_not_accepted
reset_subject(non_interactive: true)
-
+
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 1, :string, "Password:", :bool, false)
@@ -44,10 +44,10 @@ module Authentication
t2.return(USERAUTH_FAILURE, :string, "keyboard-interactive")
end
end
-
+
assert_equal false, subject.authenticate("ssh-connection", "jamis", "the-password")
end
-
+
def test_authenticate_should_be_true_if_given_password_is_accepted
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
@@ -57,10 +57,10 @@ module Authentication
t2.return(USERAUTH_SUCCESS)
end
end
-
+
assert subject.authenticate("ssh-connection", "jamis", "the-password")
end
-
+
def test_authenticate_should_duplicate_password_as_needed_to_fill_request
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
@@ -73,10 +73,10 @@ module Authentication
t2.return(USERAUTH_SUCCESS)
end
end
-
+
assert subject.authenticate("ssh-connection", "jamis", "the-password")
end
-
+
def test_authenticate_should_not_prompt_for_input_when_in_non_interactive_mode
reset_subject(non_interactive: true)
transport.expect do |t,packet|
@@ -90,16 +90,16 @@ module Authentication
t2.return(USERAUTH_SUCCESS)
end
end
-
+
assert subject.authenticate("ssh-connection", "jamis", nil)
- end
-
+ end
+
def test_authenticate_should_prompt_for_input_when_password_is_not_given
prompt = MockPrompt.new
prompt.expects(:_ask).with("Name:", anything, true).returns("name")
prompt.expects(:_ask).with("Password:", anything, false).returns("password")
reset_subject(password_prompt: prompt)
-
+
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 2, :string, "Name:", :bool, true, :string, "Password:", :bool, false)
@@ -111,16 +111,16 @@ module Authentication
t2.return(USERAUTH_SUCCESS)
end
end
-
+
assert subject.authenticate("ssh-connection", "jamis", nil)
end
-
+
private
-
+
def subject(options={})
@subject ||= Net::SSH::Authentication::Methods::KeyboardInteractive.new(session(options), options)
end
-
+
def reset_subject(options)
@subject = nil
reset_session(options)
diff --git a/test/authentication/methods/test_none.rb b/test/authentication/methods/test_none.rb
index 223b33c..bc71505 100644
--- a/test/authentication/methods/test_none.rb
+++ b/test/authentication/methods/test_none.rb
@@ -2,37 +2,37 @@ require 'common'
require 'net/ssh/authentication/methods/none'
require 'authentication/methods/common'
-module Authentication
+module Authentication
module Methods
class TestNone < NetSSHTest
include Common
-
+
def test_authenticate_should_raise_if_none_disallowed
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
assert_equal "jamis", packet.read_string
assert_equal "ssh-connection", packet.read_string
assert_equal "none", packet.read_string
-
+
t.return(USERAUTH_FAILURE, :string, "publickey")
end
-
+
assert_raises Net::SSH::Authentication::DisallowedMethod do
subject.authenticate("ssh-connection", "jamis", "pass")
end
end
-
+
def test_authenticate_should_return_true
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
t.return(USERAUTH_SUCCESS)
end
-
+
assert subject.authenticate("ssh-connection", "", "")
end
-
+
private
-
+
def subject(options={})
@subject ||= Net::SSH::Authentication::Methods::None.new(session(options), options)
end
diff --git a/test/authentication/methods/test_password.rb b/test/authentication/methods/test_password.rb
index 5fee3aa..db520bd 100644
--- a/test/authentication/methods/test_password.rb
+++ b/test/authentication/methods/test_password.rb
@@ -3,11 +3,11 @@ require 'net/ssh/authentication/methods/password'
require 'net/ssh/authentication/session'
require 'authentication/methods/common'
-module Authentication
+module Authentication
module Methods
class TestPassword < NetSSHTest
include Common
-
+
def test_authenticate_should_raise_if_password_disallowed
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
@@ -16,15 +16,15 @@ module Authentication
assert_equal "password", packet.read_string
assert_equal false, packet.read_bool
assert_equal "the-password", packet.read_string
-
+
t.return(USERAUTH_FAILURE, :string, "publickey")
end
-
+
assert_raises Net::SSH::Authentication::DisallowedMethod do
subject.authenticate("ssh-connection", "jamis", "the-password")
end
end
-
+
def test_authenticate_ask_for_password_for_second_time_when_password_is_incorrect
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
@@ -34,7 +34,7 @@ module Authentication
assert_equal false, packet.read_bool
assert_equal "the-password", packet.read_string
t.return(USERAUTH_FAILURE, :string, "publickey,password")
-
+
t.expect do |_t2, packet2|
assert_equal USERAUTH_REQUEST, packet2.type
assert_equal "jamis", packet2.read_string
@@ -45,12 +45,12 @@ module Authentication
t.return(USERAUTH_SUCCESS)
end
end
-
+
prompt = MockPrompt.new
prompt.expects(:_ask).with("jamis@'s password:", { type: 'password', user: 'jamis', host: nil }, false).returns("the-password-2")
subject(password_prompt: prompt).authenticate("ssh-connection", "jamis", "the-password")
end
-
+
def test_authenticate_ask_for_password_if_not_given
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
@@ -61,33 +61,33 @@ module Authentication
assert_equal "good-password", packet.read_string
t.return(USERAUTH_SUCCESS)
end
-
+
transport.instance_eval { @host = 'testhost' }
prompt = MockPrompt.new
prompt.expects(:_ask).with("bill@testhost's password:", { type: 'password', user: 'bill', host: 'testhost' }, false).returns("good-password")
subject(password_prompt: prompt).authenticate("ssh-connection", "bill", nil)
end
-
+
def test_authenticate_when_password_is_acceptible_should_return_true
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
t.return(USERAUTH_SUCCESS)
end
-
+
assert subject.authenticate("ssh-connection", "jamis", "the-password")
end
-
+
def test_authenticate_should_return_false_if_password_change_request_is_received
transport.expect do |t,packet|
assert_equal USERAUTH_REQUEST, packet.type
t.return(USERAUTH_PASSWD_CHANGEREQ, :string, "Change your password:", :string, "")
end
-
+
assert !subject.authenticate("ssh-connection", "jamis", "the-password")
end
-
+
private
-
+
def subject(options={})
@subject ||= Net::SSH::Authentication::Methods::Password.new(session(options), options)
end
diff --git a/test/integration/mitm_server.rb b/test/integration/mitm_server.rb
index e063687..365c318 100644
--- a/test/integration/mitm_server.rb
+++ b/test/integration/mitm_server.rb
@@ -52,7 +52,7 @@ class MitmServer < TCPServer
r,_w,_e = IO.select([local, remote],nil,nil)
if r.include? local
begin
- data = local.recv local_read_size
+ data = local.recv local_read_size
rescue StandardError => e
data = nil
dlog "Local closed: #{e}"
diff --git a/test/integration/test_curve25519sha256.rb b/test/integration/test_curve25519sha256.rb
index 0b64b62..e6a152b 100644
--- a/test/integration/test_curve25519sha256.rb
+++ b/test/integration/test_curve25519sha256.rb
@@ -28,7 +28,6 @@ unless ENV['NET_SSH_NO_ED25519']
f.close
start_sshd_7_or_later(config: config_lines) do |_pid, port|
Timeout.timeout(4) do
-
# We have our own sshd, give it a chance to come up before
# listening.
ret = Net::SSH.start("localhost", "net_ssh_1", password: 'foopwd', port: port, user_known_hosts_file: [f.path]) do |ssh|
@@ -39,7 +38,6 @@ unless ENV['NET_SSH_NO_ED25519']
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH
sleep 0.25
retry
-
end
end
end
diff --git a/test/integration/test_ed25519_pkeys.rb b/test/integration/test_ed25519_pkeys.rb
index 7ac5823..3358af7 100644
--- a/test/integration/test_ed25519_pkeys.rb
+++ b/test/integration/test_ed25519_pkeys.rb
@@ -10,7 +10,7 @@ unless ENV['NET_SSH_NO_ED25519']
# and usually connecting to net_ssh_2 user password foo2pwd
class TestED25519PKeys < NetSSHTest
include IntegrationTestHelpers
-
+
def test_in_file_no_password
Dir.mktmpdir do |dir|
sh "rm -rf #{dir}/id_rsa_ed25519 #{dir}/id_rsa_ed25519.pub"
@@ -22,8 +22,8 @@ unless ENV['NET_SSH_NO_ED25519']
end
assert_equal "hello from:net_ssh_1\n", ret
end
- end
-
+ end
+
def test_ssh_agent
Dir.mktmpdir do |dir|
with_agent do
@@ -31,10 +31,10 @@ unless ENV['NET_SSH_NO_ED25519']
sh "ssh-keygen -q -f #{dir}/id_rsa_ed25519 -t ed25519 -N 'pwd'"
set_authorized_key('net_ssh_1',"#{dir}/id_rsa_ed25519.pub")
ssh_add("#{dir}/id_rsa_ed25519","pwd")
-
+
# TODO: fix bug in net ssh which reads public key even if private key is there
sh "mv #{dir}/id_rsa_ed25519.pub #{dir}/id_rsa_ed25519.pub.hidden"
-
+
ret = Net::SSH.start("localhost", "net_ssh_1") do |ssh|
ssh.exec! 'echo "hello from:$USER"'
end
@@ -42,13 +42,13 @@ unless ENV['NET_SSH_NO_ED25519']
end
end
end
-
+
def test_in_file_with_password
Dir.mktmpdir do |dir|
sh "rm -rf #{dir}/id_rsa_ed25519 #{dir}/id_rsa_ed25519.pub"
sh "ssh-keygen -q -f #{dir}/id_rsa_ed25519 -t ed25519 -N 'pwd'"
set_authorized_key('net_ssh_1',"#{dir}/id_rsa_ed25519.pub")
-
+
# TODO: fix bug in net ssh which reads public key even if private key is there
sh "mv #{dir}/id_rsa_ed25519.pub #{dir}/id_rsa_ed25519.pub.hidden"
@@ -58,7 +58,7 @@ unless ENV['NET_SSH_NO_ED25519']
assert_equal "hello from:net_ssh_1\n", ret
end
end
-
+
def test_with_only_ed25519_host_key
config_lines = File.read('/etc/ssh/sshd_config').split("\n")
config_lines = config_lines.map do |line|
@@ -68,7 +68,7 @@ unless ENV['NET_SSH_NO_ED25519']
line
end
end
-
+
Tempfile.open('empty_kh') do |f|
f.close
with_sshd_config(config_lines.join("\n")) do
diff --git a/test/integration/test_forward.rb b/test/integration/test_forward.rb
index b84422f..75ce62f 100644
--- a/test/integration/test_forward.rb
+++ b/test/integration/test_forward.rb
@@ -51,7 +51,6 @@ class ForwardTestBase < NetSSHTest
Thread.start do
loop do
Thread.start(server.accept) do |client|
-
10000.times do |i|
client.puts "item#{i}"
end
@@ -59,7 +58,6 @@ class ForwardTestBase < NetSSHTest
rescue StandardError
exceptions << $!
raise
-
end
end
end
@@ -73,14 +71,12 @@ class TestForward < ForwardTestBase
Thread.start do
loop do
Thread.start(server.accept) do |client|
-
client.recv(1024)
client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 0].pack("ii"))
client.close
rescue StandardError
exceptions << $!
raise
-
end
end
end
@@ -187,14 +183,12 @@ class TestForward < ForwardTestBase
session.forward.local(local_port, localhost, remote_port)
client_done = Queue.new
Thread.start do
-
client = TCPSocket.new(localhost, local_port)
client.recv(1024)
client.close
sleep(0.2)
ensure
client_done << true
-
end
session.loop(0.1) { client_done.empty? }
assert_equal "Broken pipe", server_exc.pop.to_s unless server_exc.empty?
@@ -211,7 +205,6 @@ class TestForward < ForwardTestBase
session.forward.local(local_port, localhost, remote_port)
client_done = Queue.new
Thread.start do
-
client = TCPSocket.new(localhost, local_port)
client.recv(1024)
client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 0].pack("ii"))
@@ -219,7 +212,6 @@ class TestForward < ForwardTestBase
sleep(0.1)
ensure
client_done << true
-
end
session.loop(0.1) { client_done.empty? }
assert_equal "Broken pipe", server_exc.pop.to_s unless server_exc.empty?
@@ -235,7 +227,6 @@ class TestForward < ForwardTestBase
session.forward.local(local_port, localhost, remote_port)
client_done = Queue.new
Thread.start do
-
client = TCPSocket.new(localhost, local_port)
1.times do |i|
client.puts "item#{i}"
@@ -244,7 +235,6 @@ class TestForward < ForwardTestBase
sleep(0.1)
ensure
client_done << true
-
end
session.loop(0.1) { client_done.empty? }
end
@@ -273,7 +263,6 @@ class TestForward < ForwardTestBase
client.close
rescue StandardError
server_done << $!
-
end
client_done = Queue.new
got_remote_port = Queue.new
@@ -284,14 +273,12 @@ class TestForward < ForwardTestBase
session.loop(0.1) { got_remote_port.empty? }
remote_port = got_remote_port.pop
Thread.start do
-
client = TCPSocket.new(localhost, remote_port)
client.write(message)
client.close
client_done << true
rescue StandardError
client_done << $!
-
end
Timeout.timeout(5) do
session.loop(0.1) { server_done.empty? }
@@ -332,7 +319,6 @@ class TestForward < ForwardTestBase
# read on forwarded port
client_done = Queue.new
Thread.start do
-
client = TCPSocket.new(localhost, local_port)
client.read(6)
proxy.close_all
@@ -341,16 +327,13 @@ class TestForward < ForwardTestBase
client_done << true
rescue StandardError
client_done << $!
-
end
server_error = nil
Timeout.timeout(5) do
-
session.loop(0.1) { true }
rescue IOError, Errno::EBADF
server_error = $!
# puts "Error: #{$!} #{$!.backtrace.join("\n")}"
-
end
begin
Timeout.timeout(5) do
@@ -378,7 +361,6 @@ class TestForward < ForwardTestBase
# read on forwarded port
client_done = Queue.new
Thread.start do
-
client = TCPSocket.new(localhost, local_port)
client.read(6)
system("killall /bin/nc")
@@ -387,7 +369,6 @@ class TestForward < ForwardTestBase
client_done << true
rescue StandardError
client_done << $!
-
end
Timeout.timeout(5) do
begin
@@ -415,20 +396,17 @@ class TestForward < ForwardTestBase
client.close
rescue StandardError
server_done << $!
-
end
client_done = Queue.new
remote_port = server.addr[1]
local_port = session.forward.local(0, localhost, remote_port)
Thread.start do
-
client = TCPSocket.new(localhost, local_port)
client.write(message)
client.close
client_done << true
rescue StandardError
client_done << $!
-
end
Timeout.timeout(5) do
session.loop(0.1) { server_done.empty? }
@@ -454,14 +432,12 @@ class TestForward < ForwardTestBase
session.loop(0.1) { got_remote_port.empty? }
remote_port = got_remote_port.pop
Thread.start do
-
client = TCPSocket.new(localhost, remote_port)
data = client.read(4096)
client.close
client_done << data
rescue StandardError
client_done << $!
-
end
Timeout.timeout(5) do
session.loop(0.1) { client_done.empty? }
@@ -482,14 +458,12 @@ class TestForward < ForwardTestBase
remote_port = server.addr[1]
local_port = session.forward.local(0, localhost, remote_port)
Thread.start do
-
client = TCPSocket.new(localhost, local_port)
data = client.read(4096)
client.close
client_done << data
rescue StandardError
client_done << $!
-
end
Timeout.timeout(5) do
session.loop(0.1) { client_done.empty? }
@@ -500,14 +474,12 @@ class TestForward < ForwardTestBase
def _run_reading_client(client_done, local_port)
Thread.start do
-
client = TCPSocket.new(localhost, local_port)
data = client.read(4096)
client.close
client_done << data
rescue StandardError
client_done << $!
-
end
end
@@ -619,14 +591,12 @@ class TestForwardOnUnixSockets < ForwardTestBase
client_done = Queue.new
Thread.start do
-
client = UNIXSocket.new(local_socket.path)
client_data = client.recv(1024)
client.close
sleep(0.2)
ensure
client_done << true
-
end
begin
@@ -644,7 +614,7 @@ class TestForwardOnUnixSockets < ForwardTestBase
def test_forward_local_unix_socket_to_remote_socket
setup_ssh_env do
start_sshd_7_or_later do |_pid, port|
- session =
+ session =
# We have our own sshd, give it a chance to come up before
# listening.
Timeout.timeout(4) do
@@ -652,7 +622,6 @@ class TestForwardOnUnixSockets < ForwardTestBase
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH
sleep 0.25
retry
-
end
create_local_socket do |remote_socket|
diff --git a/test/integration/test_hmac_etm.rb b/test/integration/test_hmac_etm.rb
index a508061..0c7182c 100644
--- a/test/integration/test_hmac_etm.rb
+++ b/test/integration/test_hmac_etm.rb
@@ -34,7 +34,6 @@ class TestHMacEtm < NetSSHTest
define_method "test_with_only_hmac_etm#{key}" do
start_sshd_7_or_later(config: config_with_macs(variant)) do |_pid, port|
Timeout.timeout(4) do
-
# We have our own sshd, give it a chance to come up before
# listening.
ret = Net::SSH.start(
@@ -52,7 +51,6 @@ class TestHMacEtm < NetSSHTest
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH
sleep 0.25
retry
-
end
end
end
diff --git a/test/start/test_transport.rb b/test/start/test_transport.rb
index 78e3280..e94f32b 100644
--- a/test/start/test_transport.rb
+++ b/test/start/test_transport.rb
@@ -5,19 +5,19 @@ module NetSSH
class TestStart < NetSSHTest
attr_reader :transport_session
attr_reader :authentication_session
-
+
def setup
@transport_session = mock('transport_session')
@authentication_session = mock('authentication_session')
Net::SSH::Transport::Session.expects(new: transport_session)
Net::SSH::Authentication::Session.expects(new: authentication_session)
end
-
+
def test_close_transport_when_authentication_fails
authentication_session.expects(authenticate: false)
-
+
transport_session.expects(:close).at_least_once
-
+
begin
Net::SSH.start('localhost', 'testuser') {}
rescue Net::SSH::AuthenticationFailed
diff --git a/test/transport/hmac/test_md5.rb b/test/transport/hmac/test_md5.rb
index 714eee0..3188b04 100644
--- a/test/transport/hmac/test_md5.rb
+++ b/test/transport/hmac/test_md5.rb
@@ -3,36 +3,36 @@
require 'common'
require 'net/ssh/transport/hmac/md5'
-module Transport
+module Transport
module HMAC
class TestMD5 < NetSSHTest
def test_expected_digest_class
assert_equal OpenSSL::Digest::MD5, subject.digest_class
assert_equal OpenSSL::Digest::MD5, subject.new.digest_class
end
-
+
def test_expected_key_length
assert_equal 16, subject.key_length
assert_equal 16, subject.new.key_length
end
-
+
def test_expected_mac_length
assert_equal 16, subject.mac_length
assert_equal 16, subject.new.mac_length
end
-
+
def test_expected_digest
hmac = subject.new("1234567890123456")
assert_equal "\275\345\006\307y~Oi\035<.\341\031\250<\257", hmac.digest("hello world")
end
-
+
def test_key_should_be_truncated_to_required_length
hmac = subject.new("12345678901234567890")
assert_equal "1234567890123456", hmac.key
end
-
+
private
-
+
def subject
Net::SSH::Transport::HMAC::MD5
end
diff --git a/test/transport/hmac/test_md5_96.rb b/test/transport/hmac/test_md5_96.rb
index 13f4a8a..2b238e5 100644
--- a/test/transport/hmac/test_md5_96.rb
+++ b/test/transport/hmac/test_md5_96.rb
@@ -4,21 +4,21 @@ require 'common'
require 'transport/hmac/test_md5'
require 'net/ssh/transport/hmac/md5_96'
-module Transport
+module Transport
module HMAC
class TestMD5_96 < TestMD5
def test_expected_mac_length
assert_equal 12, subject.mac_length
assert_equal 12, subject.new.mac_length
end
-
+
def test_expected_digest
hmac = subject.new("1234567890123456")
assert_equal "\275\345\006\307y~Oi\035<.\341", hmac.digest("hello world")
end
-
+
private
-
+
def subject
Net::SSH::Transport::HMAC::MD5_96
end
diff --git a/test/transport/hmac/test_none.rb b/test/transport/hmac/test_none.rb
index c2661f8..812075e 100644
--- a/test/transport/hmac/test_none.rb
+++ b/test/transport/hmac/test_none.rb
@@ -1,31 +1,31 @@
require 'common'
require 'net/ssh/transport/hmac/none'
-module Transport
+module Transport
module HMAC
class TestNone < NetSSHTest
def test_expected_digest_class
assert_nil subject.digest_class
assert_nil subject.new.digest_class
end
-
+
def test_expected_key_length
assert_equal 0, subject.key_length
assert_equal 0, subject.new.key_length
end
-
+
def test_expected_mac_length
assert_equal 0, subject.mac_length
assert_equal 0, subject.new.mac_length
end
-
+
def test_expected_digest
hmac = subject.new("1234567890123456")
assert_equal "", hmac.digest("hello world")
end
-
+
private
-
+
def subject
Net::SSH::Transport::HMAC::None
end
diff --git a/test/transport/hmac/test_ripemd160.rb b/test/transport/hmac/test_ripemd160.rb
index 63ebbbd..e082485 100644
--- a/test/transport/hmac/test_ripemd160.rb
+++ b/test/transport/hmac/test_ripemd160.rb
@@ -3,31 +3,31 @@
require 'common'
require 'net/ssh/transport/hmac/ripemd160'
-module Transport
+module Transport
module HMAC
class TestRipemd160 < NetSSHTest
def test_expected_digest_class
assert_equal OpenSSL::Digest::RIPEMD160, subject.digest_class
assert_equal OpenSSL::Digest::RIPEMD160, subject.new.digest_class
end
-
+
def test_expected_key_length
assert_equal 20, subject.key_length
assert_equal 20, subject.new.key_length
end
-
+
def test_expected_mac_length
assert_equal 20, subject.mac_length
assert_equal 20, subject.new.mac_length
end
-
+
def test_expected_digest
hmac = subject.new("1234567890123456")
assert_equal "\xE4\x10\t\xB3\xD8,\x14\xA0k\x10\xB5\x0F?\x0E\x96q\x02\x16;E", hmac.digest("hello world")
end
-
+
private
-
+
def subject
Net::SSH::Transport::HMAC::RIPEMD160
end
diff --git a/test/transport/hmac/test_sha1.rb b/test/transport/hmac/test_sha1.rb
index efb9f4e..4bf3b28 100644
--- a/test/transport/hmac/test_sha1.rb
+++ b/test/transport/hmac/test_sha1.rb
@@ -3,31 +3,31 @@
require 'common'
require 'net/ssh/transport/hmac/sha1'
-module Transport
+module Transport
module HMAC
class TestSHA1 < NetSSHTest
def test_expected_digest_class
assert_equal OpenSSL::Digest::SHA1, subject.digest_class
assert_equal OpenSSL::Digest::SHA1, subject.new.digest_class
end
-
+
def test_expected_key_length
assert_equal 20, subject.key_length
assert_equal 20, subject.new.key_length
end
-
+
def test_expected_mac_length
assert_equal 20, subject.mac_length
assert_equal 20, subject.new.mac_length
end
-
+
def test_expected_digest
hmac = subject.new("1234567890123456")
assert_equal "\000\004W\202\204+&\335\311\251P\266\250\214\276\206;\022U\365", hmac.digest("hello world")
end
-
+
private
-
+
def subject
Net::SSH::Transport::HMAC::SHA1
end
diff --git a/test/transport/hmac/test_sha1_96.rb b/test/transport/hmac/test_sha1_96.rb
index 1dcf0cd..cefc16f 100644
--- a/test/transport/hmac/test_sha1_96.rb
+++ b/test/transport/hmac/test_sha1_96.rb
@@ -4,21 +4,21 @@ require 'common'
require 'transport/hmac/test_sha1'
require 'net/ssh/transport/hmac/sha1_96'
-module Transport
+module Transport
module HMAC
class TestSHA1_96 < TestSHA1
def test_expected_mac_length
assert_equal 12, subject.mac_length
assert_equal 12, subject.new.mac_length
end
-
+
def test_expected_digest
hmac = subject.new("1234567890123456")
assert_equal "\000\004W\202\204+&\335\311\251P\266", hmac.digest("hello world")
end
-
+
private
-
+
def subject
Net::SSH::Transport::HMAC::SHA1_96
end
diff --git a/test/transport/hmac/test_sha2_256_96.rb b/test/transport/hmac/test_sha2_256_96.rb
index 3a659fc..4083b1a 100644
--- a/test/transport/hmac/test_sha2_256_96.rb
+++ b/test/transport/hmac/test_sha2_256_96.rb
@@ -4,21 +4,21 @@ require 'common'
require 'transport/hmac/test_sha2_256'
require 'net/ssh/transport/hmac/sha2_256_96'
-module Transport
+module Transport
module HMAC
class TestSHA2_256_96 < TestSHA2_256
def test_expected_mac_length
assert_equal 12, subject.mac_length
assert_equal 12, subject.new.mac_length
end
-
+
def test_expected_digest
hmac = subject.new("1234567890123456")
assert_equal "\x16^>\x9FhO}\xB1>(\xBAF", hmac.digest("hello world")
end
-
+
private
-
+
def subject
Net::SSH::Transport::HMAC::SHA2_256_96
end
diff --git a/test/transport/hmac/test_sha2_512_96.rb b/test/transport/hmac/test_sha2_512_96.rb
index 16732bf..a80bc2c 100644
--- a/test/transport/hmac/test_sha2_512_96.rb
+++ b/test/transport/hmac/test_sha2_512_96.rb
@@ -4,21 +4,21 @@ require 'common'
require 'transport/hmac/test_sha2_512'
require 'net/ssh/transport/hmac/sha2_512_96'
-module Transport
+module Transport
module HMAC
class TestSHA2_512_96 < TestSHA2_512
def test_expected_mac_length
assert_equal 12, subject.mac_length
assert_equal 12, subject.new.mac_length
end
-
+
def test_expected_digest
hmac = subject.new("1234567890123456")
assert_equal "^\xB6\"\xED\x8B\xC4\xDE\xD4\xCF\xD0\r\x18", hmac.digest("hello world")
end
-
+
private
-
+
def subject
Net::SSH::Transport::HMAC::SHA2_512_96
end
diff --git a/test/transport/kex/test_diffie_hellman_group14_sha1.rb b/test/transport/kex/test_diffie_hellman_group14_sha1.rb
index ac15266..9c06c0c 100644
--- a/test/transport/kex/test_diffie_hellman_group14_sha1.rb
+++ b/test/transport/kex/test_diffie_hellman_group14_sha1.rb
@@ -3,7 +3,7 @@ require 'net/ssh/transport/kex/diffie_hellman_group14_sha1'
require_relative './test_diffie_hellman_group1_sha1'
require 'ostruct'
-module Transport
+module Transport
module Kex
class TestDiffieHellmanGroup14SHA1 < TestDiffieHellmanGroup1SHA1
def subject
diff --git a/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb b/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb
index b709dda..29a7d36 100644
--- a/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb
+++ b/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb
@@ -2,60 +2,60 @@ require 'common'
require 'transport/kex/test_diffie_hellman_group1_sha1'
require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
-module Transport
+module Transport
module Kex
class TestDiffieHellmanGroupExchangeSHA1 < TestDiffieHellmanGroup1SHA1
KEXDH_GEX_GROUP = 31
KEXDH_GEX_INIT = 32
KEXDH_GEX_REPLY = 33
KEXDH_GEX_REQUEST = 34
-
+
def test_exchange_with_fewer_than_minimum_bits_uses_minimum_bits
dh_options need_bytes: 20
assert_equal 1024, need_bits
assert_nothing_raised { exchange! }
end
-
+
def test_exchange_with_optional_minimum_bits_declared
dh_options minimum_dh_bits: 4096
assert_equal 4096, need_bits
assert_nothing_raised { exchange! }
end
-
+
def test_exchange_with_fewer_than_maximum_bits_uses_need_bits
dh_options need_bytes: 500
need_bits(8001)
assert_nothing_raised { exchange! }
end
-
+
def test_exchange_with_more_than_maximum_bits_uses_maximum_bits
dh_options need_bytes: 2000
need_bits(8192)
assert_nothing_raised { exchange! }
end
-
+
def test_that_p_and_g_are_provided_by_the_server
assert_nothing_raised { exchange! p: default_p + 2, g: 3 }
assert_equal default_p + 2, dh.dh.p
assert_equal 3, dh.dh.g
end
-
+
private
-
+
def need_bits(bits=1024)
@need_bits ||= need_minimum(bits)
end
-
+
def need_minimum(bits=1024)
return @dh_options[:minimum_dh_bits] if @dh_options && @dh_options[:minimum_dh_bits]
bits
end
-
+
def default_p
142326151570335518660743995281621698377057354949884468943021767573608899048361360422513557553514790045512299468953431585300812548859419857171094366358158903433167915517332113861059747425408670144201099811846875730766487278261498262568348338476437200556998366087779709990807518291581860338635288400119315130179
end
-
+
def exchange!(options={})
connection.expect do |t, buffer|
assert_equal KEXDH_GEX_REQUEST, buffer.type
@@ -73,18 +73,18 @@ module Transport
end
end
end
-
+
dh.exchange_keys
end
-
+
def subject
Net::SSH::Transport::Kex::DiffieHellmanGroupExchangeSHA1
end
-
+
def digest_type
OpenSSL::Digest::SHA1
end
-
+
def session_id
@session_id ||= begin
buffer = Net::SSH::Buffer.from(:string, packet_data[:client_version_string],
diff --git a/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb b/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb
index 95f4152..d3d6d76 100644
--- a/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb
+++ b/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb
@@ -2,15 +2,15 @@ require 'common'
require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
require 'transport/kex/test_diffie_hellman_group_exchange_sha1'
-module Transport
+module Transport
module Kex
class TestDiffieHellmanGroupExchangeSHA256 < TestDiffieHellmanGroupExchangeSHA1
private
-
+
def subject
Net::SSH::Transport::Kex::DiffieHellmanGroupExchangeSHA256
end
-
+
def digest_type
OpenSSL::Digest::SHA256
end
diff --git a/test/transport/test_state.rb b/test/transport/test_state.rb
index b08fda7..389f012 100644
--- a/test/transport/test_state.rb
+++ b/test/transport/test_state.rb
@@ -114,7 +114,7 @@ module Transport
end
def test_compress_when_compression_is_enabled_should_return_compressed_text
- state.set compression: :standard
+ state.set compression: :standard
# JRuby Zlib implementation (1.4 & 1.5) does not have byte-to-byte compatibility with MRI's.
# skip this test under JRuby.
return if defined?(JRUBY_VERSION)
@@ -123,7 +123,7 @@ module Transport
end
def test_decompress_when_compression_is_enabled_should_return_decompressed_text
- state.set compression: :standard
+ state.set compression: :standard
# JRuby Zlib implementation (1.4 & 1.5) does not have byte-to-byte compatibility with MRI's.
# skip this test under JRuby.
return if defined?(JRUBY_VERSION)
diff --git a/test/win_integration/test_pageant.rb b/test/win_integration/test_pageant.rb
index f87fe59..b7e89fa 100644
--- a/test/win_integration/test_pageant.rb
+++ b/test/win_integration/test_pageant.rb
@@ -15,21 +15,21 @@ module Authentication
ensure
Process.kill(9, pageant_pid)
end
-
+
def test_agent_should_be_able_to_negotiate_with_pagent
with_pagent do
agent.negotiate!
end
end
-
+
def test_agent_should_raise_without_pagent
assert_raises Net::SSH::Authentication::AgentNotAvailable do
agent.negotiate!
end
end
-
+
private
-
+
def agent(auto=:connect)
@agent ||= begin
agent = Net::SSH::Authentication::Agent.new