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-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.


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

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.


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

def algorithms
  @algorithms
end

#compression_clientObject (readonly)

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


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

def compression_client
  @compression_client
end

#compression_serverObject (readonly)

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


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

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.


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

def encryption_client
  @encryption_client
end

#encryption_serverObject (readonly)

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


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

def encryption_server
  @encryption_server
end

#hmac_clientObject (readonly)

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


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

def hmac_client
  @hmac_client
end

#hmac_serverObject (readonly)

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


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

def hmac_server
  @hmac_server
end

#host_keyObject (readonly)

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


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

def host_key
  @host_key
end

#kexObject (readonly)

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


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

def kex
  @kex
end

#language_clientObject (readonly)

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


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

def language_client
  @language_client
end

#language_serverObject (readonly)

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


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

def language_server
  @language_server
end

#optionsObject (readonly)

The hash of options used to initialize this object


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

def options
  @options
end

#sessionObject (readonly)

The underlying transport layer session that supports this object


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

def session
  @session
end

#session_idObject (readonly)

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


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

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:

  • (Boolean)

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

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).


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

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.


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

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:

  • (Boolean)

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

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

#host_key_formatObject


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

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:

  • (Boolean)

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

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:

  • (Boolean)

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

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.


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

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

#startObject

Start the algorithm negotation

Raises:

  • (ArgumentError)

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

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

  send_kexinit
end