Class: Net::SSH::Transport::Algorithms

Inherits:
Object
  • Object
show all
Includes:
Loggable, Constants
Defined in:
lib/net/ssh/transport/algorithms.rb

Overview

Implements the higher-level logic behind an SSH key-exchange. It handles both the initial exchange, as well as subsequent re-exchanges (as needed). It also encapsulates the negotiation of the algorithms, and provides a single point of access to the negotiated algorithms.

You will never instantiate or reference this directly. It is used internally by the transport layer.

Constant Summary collapse

DEFAULT_ALGORITHMS =

Define the default algorithms, in order of preference, supported by Net::SSH.

{
  host_key: %w[[email protected]
               [email protected]
               [email protected]
               ecdsa-sha2-nistp521
               ecdsa-sha2-nistp384
               ecdsa-sha2-nistp256
               [email protected]
               [email protected]
               ssh-rsa
               rsa-sha2-256
               rsa-sha2-512],

  kex: %w[ecdh-sha2-nistp521
          ecdh-sha2-nistp384
          ecdh-sha2-nistp256
          diffie-hellman-group-exchange-sha256
          diffie-hellman-group14-sha256
          diffie-hellman-group14-sha1],

  encryption: %w[aes256-ctr aes192-ctr aes128-ctr],

  hmac: %w[[email protected] [email protected]
           hmac-sha2-512 hmac-sha2-256
           hmac-sha1]
}.freeze
ALGORITHMS =

Define all algorithms, with the deprecated, supported by Net::SSH.

{
  host_key: DEFAULT_ALGORITHMS[:host_key] + %w[ssh-dss],

  kex: DEFAULT_ALGORITHMS[:kex] +
       %w[diffie-hellman-group-exchange-sha1
          diffie-hellman-group1-sha1],

  encryption: DEFAULT_ALGORITHMS[:encryption] +
              %w[aes256-cbc aes192-cbc aes128-cbc
                 [email protected]
                 blowfish-ctr blowfish-cbc
                 cast128-ctr cast128-cbc
                 3des-ctr 3des-cbc
                 idea-cbc
                 none],

  hmac: DEFAULT_ALGORITHMS[:hmac] +
        %w[hmac-sha2-512-96 hmac-sha2-256-96
           hmac-sha1-96
           hmac-ripemd160 [email protected]
           hmac-md5 hmac-md5-96
           none],

  compression: %w[none [email protected] zlib],
  language: %w[]
}.freeze

Constants included from Constants

Constants::DEBUG, Constants::DISCONNECT, Constants::IGNORE, Constants::KEXDH_GEX_GROUP, Constants::KEXDH_GEX_INIT, Constants::KEXDH_GEX_REPLY, Constants::KEXDH_GEX_REQUEST, Constants::KEXDH_INIT, Constants::KEXDH_REPLY, Constants::KEXECDH_INIT, Constants::KEXECDH_REPLY, Constants::KEXINIT, Constants::NEWKEYS, Constants::SERVICE_ACCEPT, Constants::SERVICE_REQUEST, Constants::UNIMPLEMENTED

Instance Attribute Summary collapse

Attributes included from Loggable

#logger

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Loggable

#debug, #error, #fatal, #info, #lwarn

Constructor Details

#initialize(session, options = {}) ⇒ Algorithms

Instantiates a new Algorithms object, and prepares the hash of preferred algorithms based on the options parameter and the ALGORITHMS constant.



149
150
151
152
153
154
155
156
157
# File 'lib/net/ssh/transport/algorithms.rb', line 149

def initialize(session, options = {})
  @session = session
  @logger = session.logger
  @options = options
  @algorithms = {}
  @pending = @initialized = false
  @client_packet = @server_packet = nil
  prepare_preferred_algorithms!
end

Instance Attribute Details

#algorithmsObject (readonly)

The hash of algorithms preferred by the client, which will be told to the server during algorithm negotiation.



135
136
137
# File 'lib/net/ssh/transport/algorithms.rb', line 135

def algorithms
  @algorithms
end

#compression_clientObject (readonly)

The type of compression to use to compress packets being sent by the client.



122
123
124
# File 'lib/net/ssh/transport/algorithms.rb', line 122

def compression_client
  @compression_client
end

#compression_serverObject (readonly)

The type of compression to use to decompress packets arriving from the server.



125
126
127
# File 'lib/net/ssh/transport/algorithms.rb', line 125

def compression_server
  @compression_server
end

#encryption_clientObject (readonly)

The type of the cipher to use to encrypt packets sent from the client to the server.



110
111
112
# File 'lib/net/ssh/transport/algorithms.rb', line 110

def encryption_client
  @encryption_client
end

#encryption_serverObject (readonly)

The type of the cipher to use to decrypt packets arriving from the server.



113
114
115
# File 'lib/net/ssh/transport/algorithms.rb', line 113

def encryption_server
  @encryption_server
end

#hmac_clientObject (readonly)

The type of HMAC to use to sign packets sent by the client.



116
117
118
# File 'lib/net/ssh/transport/algorithms.rb', line 116

def hmac_client
  @hmac_client
end

#hmac_serverObject (readonly)

The type of HMAC to use to validate packets arriving from the server.



119
120
121
# File 'lib/net/ssh/transport/algorithms.rb', line 119

def hmac_server
  @hmac_server
end

#host_keyObject (readonly)

The type of host key that will be used for this session.



106
107
108
# File 'lib/net/ssh/transport/algorithms.rb', line 106

def host_key
  @host_key
end

#kexObject (readonly)

The kex algorithm to use settled on between the client and server.



103
104
105
# File 'lib/net/ssh/transport/algorithms.rb', line 103

def kex
  @kex
end

#language_clientObject (readonly)

The language that will be used in messages sent by the client.



128
129
130
# File 'lib/net/ssh/transport/algorithms.rb', line 128

def language_client
  @language_client
end

#language_serverObject (readonly)

The language that will be used in messages sent from the server.



131
132
133
# File 'lib/net/ssh/transport/algorithms.rb', line 131

def language_server
  @language_server
end

#optionsObject (readonly)

The hash of options used to initialize this object



100
101
102
# File 'lib/net/ssh/transport/algorithms.rb', line 100

def options
  @options
end

#sessionObject (readonly)

The underlying transport layer session that supports this object



97
98
99
# File 'lib/net/ssh/transport/algorithms.rb', line 97

def session
  @session
end

#session_idObject (readonly)

The session-id for this session, as decided during the initial key exchange.



138
139
140
# File 'lib/net/ssh/transport/algorithms.rb', line 138

def session_id
  @session_id
end

Class Method Details

.allowed_packet?(packet) ⇒ Boolean

Returns true if the given packet can be processed during a key-exchange.

Returns:



141
142
143
144
145
# File 'lib/net/ssh/transport/algorithms.rb', line 141

def self.allowed_packet?(packet)
  (1..4).include?(packet.type) ||
  (6..19).include?(packet.type) ||
  (21..49).include?(packet.type)
end

Instance Method Details

#[](key) ⇒ Object

A convenience method for accessing the list of preferred types for a specific algorithm (see #algorithms).



193
194
195
# File 'lib/net/ssh/transport/algorithms.rb', line 193

def [](key)
  algorithms[key]
end

#accept_kexinit(packet) ⇒ Object

Called by the transport layer when a KEXINIT packet is received, indicating that the server wants to exchange keys. This can be spontaneous, or it can be in response to a client-initiated rekey request (see #rekey!). Either way, this will block until the key exchange completes.



180
181
182
183
184
185
186
187
188
189
# File 'lib/net/ssh/transport/algorithms.rb', line 180

def accept_kexinit(packet)
  info { "got KEXINIT from server" }
  @server_data = parse_server_algorithm_packet(packet)
  @server_packet = @server_data[:raw]
  if !pending?
    send_kexinit
  else
    proceed!
  end
end

#allow?(packet) ⇒ Boolean

Returns true if no exchange is pending, and otherwise returns true or false depending on whether the given packet is of a type that is allowed during a key exchange.

Returns:



209
210
211
# File 'lib/net/ssh/transport/algorithms.rb', line 209

def allow?(packet)
  !pending? || Algorithms.allowed_packet?(packet)
end

#host_key_formatObject



218
219
220
221
222
223
224
225
# File 'lib/net/ssh/transport/algorithms.rb', line 218

def host_key_format
  case host_key
  when /^([a-z0-9-]+)-cert-v\d{2}@openssh.com$/
    Regexp.last_match[1]
  else
    host_key
  end
end

#initialized?Boolean

Returns true if the algorithms have been negotiated at all.

Returns:



214
215
216
# File 'lib/net/ssh/transport/algorithms.rb', line 214

def initialized?
  @initialized
end

#pending?Boolean

Returns true if a key-exchange is pending. This will be true from the moment either the client or server requests the key exchange, until the exchange completes. While an exchange is pending, only a limited number of packets are allowed, so event processing essentially stops during this period.

Returns:



202
203
204
# File 'lib/net/ssh/transport/algorithms.rb', line 202

def pending?
  @pending
end

#rekey!Object

Request a rekey operation. This will return immediately, and does not actually perform the rekey operation. It does cause the session to change state, however--until the key exchange finishes, no new packets will be processed.



170
171
172
173
174
# File 'lib/net/ssh/transport/algorithms.rb', line 170

def rekey!
  @client_packet = @server_packet = nil
  @initialized = false
  send_kexinit
end

#startObject

Start the algorithm negotation

Raises:



160
161
162
163
164
# File 'lib/net/ssh/transport/algorithms.rb', line 160

def start
  raise ArgumentError, "Cannot call start if it's negotiation started or done" if @pending || @initialized

  send_kexinit
end