Class: ESSH::Transport::Algorithms

Inherits:
Object
  • Object
show all
Includes:
Net::SSH::Loggable, Net::SSH::Transport::Constants
Defined in:
lib/evented-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

ALGORITHMS =

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

{
    host_key: %w(ssh-rsa ssh-dss
                [email protected]
                [email protected]),
    kex: %w(diffie-hellman-group-exchange-sha1
            diffie-hellman-group1-sha1
            diffie-hellman-group14-sha1
            diffie-hellman-group-exchange-sha256),
    encryption: %w(aes128-cbc 3des-cbc blowfish-cbc cast128-cbc
                aes192-cbc aes256-cbc [email protected]
                idea-cbc arcfour128 arcfour256 arcfour
                aes128-ctr aes192-ctr aes256-ctr
                cast128-ctr blowfish-ctr 3des-ctr none),

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

    compression: %w(none [email protected] zlib),
    language: %w()
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

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.



105
106
107
108
109
110
111
112
113
114
115
# File 'lib/evented-ssh/transport/algorithms.rb', line 105

def initialize(session, options={})
    @session = session
    @logger = session.logger
    @options = options
    @algorithms = {}
    @ready = @session.reactor.defer
    @pending = nil
    @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.



91
92
93
# File 'lib/evented-ssh/transport/algorithms.rb', line 91

def algorithms
  @algorithms
end

#compression_clientObject (readonly)

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



78
79
80
# File 'lib/evented-ssh/transport/algorithms.rb', line 78

def compression_client
  @compression_client
end

#compression_serverObject (readonly)

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



81
82
83
# File 'lib/evented-ssh/transport/algorithms.rb', line 81

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.



66
67
68
# File 'lib/evented-ssh/transport/algorithms.rb', line 66

def encryption_client
  @encryption_client
end

#encryption_serverObject (readonly)

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



69
70
71
# File 'lib/evented-ssh/transport/algorithms.rb', line 69

def encryption_server
  @encryption_server
end

#hmac_clientObject (readonly)

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



72
73
74
# File 'lib/evented-ssh/transport/algorithms.rb', line 72

def hmac_client
  @hmac_client
end

#hmac_serverObject (readonly)

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



75
76
77
# File 'lib/evented-ssh/transport/algorithms.rb', line 75

def hmac_server
  @hmac_server
end

#host_keyObject (readonly)

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



62
63
64
# File 'lib/evented-ssh/transport/algorithms.rb', line 62

def host_key
  @host_key
end

#kexObject (readonly)

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



59
60
61
# File 'lib/evented-ssh/transport/algorithms.rb', line 59

def kex
  @kex
end

#language_clientObject (readonly)

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



84
85
86
# File 'lib/evented-ssh/transport/algorithms.rb', line 84

def language_client
  @language_client
end

#language_serverObject (readonly)

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



87
88
89
# File 'lib/evented-ssh/transport/algorithms.rb', line 87

def language_server
  @language_server
end

#optionsObject (readonly)

The hash of options used to initialize this object



56
57
58
# File 'lib/evented-ssh/transport/algorithms.rb', line 56

def options
  @options
end

#sessionObject (readonly)

The underlying transport layer session that supports this object



53
54
55
# File 'lib/evented-ssh/transport/algorithms.rb', line 53

def session
  @session
end

#session_idObject (readonly)

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



94
95
96
# File 'lib/evented-ssh/transport/algorithms.rb', line 94

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)


97
98
99
100
101
# File 'lib/evented-ssh/transport/algorithms.rb', line 97

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



159
160
161
# File 'lib/evented-ssh/transport/algorithms.rb', line 159

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.



146
147
148
149
150
151
152
153
154
155
# File 'lib/evented-ssh/transport/algorithms.rb', line 146

def accept_kexinit(packet)
    info { "got KEXINIT from server" }
    @server_data = parse_server_algorithm_packet(packet)
    @server_packet = @server_data[:raw]
    if @pending.nil?
        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)


175
176
177
# File 'lib/evented-ssh/transport/algorithms.rb', line 175

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

#initialized?Boolean

Returns true if the algorithms have been negotiated at all.

Returns:

  • (Boolean)


180
181
182
# File 'lib/evented-ssh/transport/algorithms.rb', line 180

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)


168
169
170
# File 'lib/evented-ssh/transport/algorithms.rb', line 168

def pending?
    @pending
end

#readyObject



123
124
125
# File 'lib/evented-ssh/transport/algorithms.rb', line 123

def ready
    @ready.promise.value
end

#reject(error) ⇒ Object



127
128
129
130
# File 'lib/evented-ssh/transport/algorithms.rb', line 127

def reject(error)
    @ready.reject(error)
    @pending.reject(error) if @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.



136
137
138
139
140
# File 'lib/evented-ssh/transport/algorithms.rb', line 136

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

#startObject

Start the algorithm negotation

Raises:

  • (ArgumentError)


118
119
120
121
# File 'lib/evented-ssh/transport/algorithms.rb', line 118

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