net-ssh 6.1.0 → 7.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +2 -1
- data/.dockerignore +6 -0
- data/.github/config/rubocop_linter_action.yml +4 -0
- data/.github/workflows/ci-with-docker.yml +44 -0
- data/.github/workflows/ci.yml +87 -0
- data/.github/workflows/rubocop.yml +16 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +12 -1
- data/.rubocop_todo.yml +474 -375
- data/CHANGES.txt +40 -3
- data/Dockerfile +27 -0
- data/Dockerfile.openssl3 +17 -0
- data/Gemfile +2 -0
- data/Gemfile.noed25519 +2 -0
- data/README.md +14 -4
- data/Rakefile +59 -0
- data/SECURITY.md +4 -0
- data/docker-compose.yml +23 -0
- data/lib/net/ssh/authentication/agent.rb +29 -13
- data/lib/net/ssh/authentication/certificate.rb +14 -11
- data/lib/net/ssh/authentication/constants.rb +0 -1
- data/lib/net/ssh/authentication/ed25519.rb +12 -7
- data/lib/net/ssh/authentication/ed25519_loader.rb +4 -7
- data/lib/net/ssh/authentication/key_manager.rb +46 -34
- data/lib/net/ssh/authentication/methods/abstract.rb +12 -3
- data/lib/net/ssh/authentication/methods/hostbased.rb +3 -5
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +2 -2
- data/lib/net/ssh/authentication/methods/none.rb +6 -9
- data/lib/net/ssh/authentication/methods/password.rb +2 -3
- data/lib/net/ssh/authentication/methods/publickey.rb +56 -16
- data/lib/net/ssh/authentication/pageant.rb +97 -97
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +2 -2
- data/lib/net/ssh/authentication/session.rb +18 -17
- data/lib/net/ssh/buffer.rb +71 -51
- data/lib/net/ssh/buffered_io.rb +24 -25
- data/lib/net/ssh/config.rb +33 -20
- data/lib/net/ssh/connection/channel.rb +84 -82
- data/lib/net/ssh/connection/constants.rb +0 -4
- data/lib/net/ssh/connection/event_loop.rb +30 -24
- data/lib/net/ssh/connection/keepalive.rb +12 -12
- data/lib/net/ssh/connection/session.rb +109 -108
- data/lib/net/ssh/connection/term.rb +56 -58
- data/lib/net/ssh/errors.rb +12 -12
- data/lib/net/ssh/key_factory.rb +7 -8
- data/lib/net/ssh/known_hosts.rb +84 -15
- data/lib/net/ssh/loggable.rb +8 -9
- data/lib/net/ssh/packet.rb +1 -1
- data/lib/net/ssh/prompt.rb +9 -11
- data/lib/net/ssh/proxy/command.rb +1 -1
- data/lib/net/ssh/proxy/errors.rb +2 -4
- data/lib/net/ssh/proxy/http.rb +18 -20
- data/lib/net/ssh/proxy/https.rb +8 -10
- data/lib/net/ssh/proxy/jump.rb +8 -10
- data/lib/net/ssh/proxy/socks4.rb +2 -4
- data/lib/net/ssh/proxy/socks5.rb +3 -5
- data/lib/net/ssh/service/forward.rb +7 -7
- data/lib/net/ssh/test/channel.rb +24 -26
- data/lib/net/ssh/test/extensions.rb +35 -35
- data/lib/net/ssh/test/kex.rb +6 -8
- data/lib/net/ssh/test/local_packet.rb +0 -2
- data/lib/net/ssh/test/packet.rb +3 -3
- data/lib/net/ssh/test/remote_packet.rb +6 -8
- data/lib/net/ssh/test/script.rb +25 -27
- data/lib/net/ssh/test/socket.rb +12 -15
- data/lib/net/ssh/test.rb +4 -5
- data/lib/net/ssh/transport/algorithms.rb +17 -14
- data/lib/net/ssh/transport/cipher_factory.rb +28 -28
- data/lib/net/ssh/transport/constants.rb +3 -3
- data/lib/net/ssh/transport/ctr.rb +7 -7
- data/lib/net/ssh/transport/hmac/abstract.rb +4 -5
- data/lib/net/ssh/transport/hmac/md5.rb +0 -2
- data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
- data/lib/net/ssh/transport/hmac/none.rb +0 -2
- data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
- data/lib/net/ssh/transport/hmac.rb +12 -12
- data/lib/net/ssh/transport/identity_cipher.rb +11 -13
- data/lib/net/ssh/transport/kex/abstract.rb +12 -5
- data/lib/net/ssh/transport/kex/abstract5656.rb +1 -1
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +2 -1
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +4 -4
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +21 -21
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -2
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +2 -2
- data/lib/net/ssh/transport/kex.rb +8 -6
- data/lib/net/ssh/transport/key_expander.rb +7 -8
- data/lib/net/ssh/transport/openssl.rb +51 -26
- data/lib/net/ssh/transport/packet_stream.rb +2 -3
- data/lib/net/ssh/transport/server_version.rb +17 -16
- data/lib/net/ssh/transport/session.rb +9 -7
- data/lib/net/ssh/transport/state.rb +43 -43
- data/lib/net/ssh/verifiers/accept_new.rb +0 -2
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
- data/lib/net/ssh/verifiers/always.rb +6 -4
- data/lib/net/ssh/verifiers/never.rb +0 -2
- data/lib/net/ssh/version.rb +1 -1
- data/lib/net/ssh.rb +10 -6
- data/net-ssh-public_cert.pem +8 -8
- data/net-ssh.gemspec +2 -2
- data/support/ssh_tunnel_bug.rb +3 -3
- data.tar.gz.sig +0 -0
- metadata +24 -15
- metadata.gz.sig +0 -0
- data/.travis.yml +0 -52
@@ -1,7 +1,6 @@
|
|
1
|
-
module Net
|
2
|
-
module SSH
|
1
|
+
module Net
|
2
|
+
module SSH
|
3
3
|
module Connection
|
4
|
-
|
5
4
|
# These constants are used when requesting a pseudo-terminal (via
|
6
5
|
# Net::SSH::Connection::Channel#request_pty). The descriptions for each are
|
7
6
|
# taken directly from RFC 4254 ("The Secure Shell (SSH) Connection Protocol"),
|
@@ -10,173 +9,172 @@ module Net
|
|
10
9
|
# Interrupt character; 255 if none. Similarly for the other characters.
|
11
10
|
# Not all of these characters are supported on all systems.
|
12
11
|
VINTR = 1
|
13
|
-
|
12
|
+
|
14
13
|
# The quit character (sends SIGQUIT signal on POSIX systems).
|
15
14
|
VQUIT = 2
|
16
|
-
|
15
|
+
|
17
16
|
# Erase the character to left of the cursor.
|
18
17
|
VERASE = 3
|
19
|
-
|
18
|
+
|
20
19
|
# Kill the current input line.
|
21
20
|
VKILL = 4
|
22
|
-
|
21
|
+
|
23
22
|
# End-of-file character (sends EOF from the terminal).
|
24
23
|
VEOF = 5
|
25
|
-
|
24
|
+
|
26
25
|
# End-of-line character in addition to carriage return and/or linefeed.
|
27
26
|
VEOL = 6
|
28
|
-
|
27
|
+
|
29
28
|
# Additional end-of-line character.
|
30
29
|
VEOL2 = 7
|
31
|
-
|
30
|
+
|
32
31
|
# Continues paused output (normally control-Q).
|
33
32
|
VSTART = 8
|
34
|
-
|
33
|
+
|
35
34
|
# Pauses output (normally control-S).
|
36
35
|
VSTOP = 9
|
37
|
-
|
36
|
+
|
38
37
|
# Suspends the current program.
|
39
38
|
VSUSP = 10
|
40
|
-
|
39
|
+
|
41
40
|
# Another suspend character.
|
42
41
|
VDSUSP = 11
|
43
|
-
|
42
|
+
|
44
43
|
# Reprints the current input line.
|
45
44
|
VREPRINT = 12
|
46
|
-
|
45
|
+
|
47
46
|
# Erases a word left of cursor.
|
48
47
|
VWERASE = 13
|
49
|
-
|
48
|
+
|
50
49
|
# Enter the next character typed literally, even if it is a special
|
51
50
|
# character.
|
52
51
|
VLNEXT = 14
|
53
|
-
|
52
|
+
|
54
53
|
# Character to flush output.
|
55
54
|
VFLUSH = 15
|
56
|
-
|
55
|
+
|
57
56
|
# Switch to a different shell layer.
|
58
57
|
VSWITCH = 16
|
59
|
-
|
58
|
+
|
60
59
|
# Prints system status line (load, command, pid, etc).
|
61
60
|
VSTATUS = 17
|
62
|
-
|
61
|
+
|
63
62
|
# Toggles the flushing of terminal output.
|
64
63
|
VDISCARD = 18
|
65
|
-
|
64
|
+
|
66
65
|
# The ignore parity flag. The parameter SHOULD be 0 if this flag is FALSE,
|
67
66
|
# and 1 if it is TRUE.
|
68
67
|
IGNPAR = 30
|
69
|
-
|
68
|
+
|
70
69
|
# Mark parity and framing errors.
|
71
70
|
PARMRK = 31
|
72
|
-
|
71
|
+
|
73
72
|
# Enable checking of parity errors.
|
74
73
|
INPCK = 32
|
75
|
-
|
74
|
+
|
76
75
|
# Strip 8th bit off characters.
|
77
76
|
ISTRIP = 33
|
78
|
-
|
77
|
+
|
79
78
|
# Map NL into CR on input.
|
80
79
|
INCLR = 34
|
81
|
-
|
80
|
+
|
82
81
|
# Ignore CR on input.
|
83
82
|
IGNCR = 35
|
84
|
-
|
83
|
+
|
85
84
|
# Map CR to NL on input.
|
86
85
|
ICRNL = 36
|
87
|
-
|
86
|
+
|
88
87
|
# Translate uppercase characters to lowercase.
|
89
88
|
IUCLC = 37
|
90
|
-
|
89
|
+
|
91
90
|
# Enable output flow control.
|
92
91
|
IXON = 38
|
93
|
-
|
92
|
+
|
94
93
|
# Any char will restart after stop.
|
95
94
|
IXANY = 39
|
96
|
-
|
95
|
+
|
97
96
|
# Enable input flow control.
|
98
97
|
IXOFF = 40
|
99
|
-
|
98
|
+
|
100
99
|
# Ring bell on input queue full.
|
101
100
|
IMAXBEL = 41
|
102
|
-
|
101
|
+
|
103
102
|
# Enable signals INTR, QUIT, [D]SUSP.
|
104
103
|
ISIG = 50
|
105
|
-
|
104
|
+
|
106
105
|
# Canonicalize input lines.
|
107
106
|
ICANON = 51
|
108
|
-
|
107
|
+
|
109
108
|
# Enable input and output of uppercase characters by preceding their
|
110
109
|
# lowercase equivalents with "\".
|
111
110
|
XCASE = 52
|
112
|
-
|
111
|
+
|
113
112
|
# Enable echoing.
|
114
113
|
ECHO = 53
|
115
|
-
|
114
|
+
|
116
115
|
# Visually erase chars.
|
117
116
|
ECHOE = 54
|
118
|
-
|
117
|
+
|
119
118
|
# Kill character discards current line.
|
120
119
|
ECHOK = 55
|
121
|
-
|
120
|
+
|
122
121
|
# Echo NL even if ECHO is off.
|
123
122
|
ECHONL = 56
|
124
|
-
|
123
|
+
|
125
124
|
# Don't flush after interrupt.
|
126
125
|
NOFLSH = 57
|
127
|
-
|
126
|
+
|
128
127
|
# Stop background jobs from output.
|
129
128
|
TOSTOP = 58
|
130
|
-
|
129
|
+
|
131
130
|
# Enable extensions.
|
132
131
|
IEXTEN = 59
|
133
|
-
|
132
|
+
|
134
133
|
# Echo control characters as ^(Char).
|
135
134
|
ECHOCTL = 60
|
136
|
-
|
135
|
+
|
137
136
|
# Visual erase for line kill.
|
138
137
|
ECHOKE = 61
|
139
|
-
|
138
|
+
|
140
139
|
# Retype pending input.
|
141
140
|
PENDIN = 62
|
142
|
-
|
141
|
+
|
143
142
|
# Enable output processing.
|
144
143
|
OPOST = 70
|
145
|
-
|
144
|
+
|
146
145
|
# Convert lowercase to uppercase.
|
147
146
|
OLCUC = 71
|
148
|
-
|
147
|
+
|
149
148
|
# Map NL to CR-NL.
|
150
149
|
ONLCR = 72
|
151
|
-
|
150
|
+
|
152
151
|
# Translate carriage return to newline (output).
|
153
152
|
OCRNL = 73
|
154
|
-
|
153
|
+
|
155
154
|
# Translate newline to carriage return-newline (output).
|
156
155
|
ONOCR = 74
|
157
|
-
|
156
|
+
|
158
157
|
# Newline performs a carriage return (output).
|
159
158
|
ONLRET = 75
|
160
|
-
|
159
|
+
|
161
160
|
# 7 bit mode.
|
162
161
|
CS7 = 90
|
163
|
-
|
162
|
+
|
164
163
|
# 8 bit mode.
|
165
164
|
CS8 = 91
|
166
|
-
|
165
|
+
|
167
166
|
# Parity enable.
|
168
167
|
PARENB = 92
|
169
|
-
|
168
|
+
|
170
169
|
# Odd parity, else even.
|
171
170
|
PARODD = 93
|
172
|
-
|
171
|
+
|
173
172
|
# Specifies the input baud rate in bits per second.
|
174
173
|
TTY_OP_ISPEED = 128
|
175
|
-
|
174
|
+
|
176
175
|
# Specifies the output baud rate in bits per second.
|
177
176
|
TTY_OP_OSPEED = 129
|
178
177
|
end
|
179
|
-
|
180
178
|
end
|
181
179
|
end
|
182
180
|
end
|
data/lib/net/ssh/errors.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
module Net
|
1
|
+
module Net
|
2
2
|
module SSH
|
3
3
|
# A general exception class, to act as the ancestor of all other Net::SSH
|
4
4
|
# exception classes.
|
@@ -33,7 +33,7 @@ module Net
|
|
33
33
|
# a "channel open failed" message.
|
34
34
|
class ChannelOpenFailed < Net::SSH::Exception
|
35
35
|
attr_reader :code, :reason
|
36
|
-
|
36
|
+
|
37
37
|
def initialize(code, reason)
|
38
38
|
@code, @reason = code, reason
|
39
39
|
super "#{reason} (#{code})"
|
@@ -45,43 +45,43 @@ module Net
|
|
45
45
|
# the remember_host! method on the exception, and then retry.
|
46
46
|
class HostKeyError < Net::SSH::Exception
|
47
47
|
# the callback to use when #remember_host! is called
|
48
|
-
attr_writer :callback
|
49
|
-
|
48
|
+
attr_writer :callback # :nodoc:
|
49
|
+
|
50
50
|
# situation-specific data describing the host (see #host, #port, etc.)
|
51
|
-
attr_writer :data
|
52
|
-
|
51
|
+
attr_writer :data # :nodoc:
|
52
|
+
|
53
53
|
# An accessor for getting at the data that was used to look up the host
|
54
54
|
# (see also #fingerprint, #host, #port, #ip, and #key).
|
55
55
|
def [](key)
|
56
56
|
@data && @data[key]
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
# Returns the fingerprint of the key for the host, which either was not
|
60
60
|
# found or did not match.
|
61
61
|
def fingerprint
|
62
62
|
@data && @data[:fingerprint]
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
# Returns the host name for the remote host, as reported by the socket.
|
66
66
|
def host
|
67
67
|
@data && @data[:peer] && @data[:peer][:host]
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
# Returns the port number for the remote host, as reported by the socket.
|
71
71
|
def port
|
72
72
|
@data && @data[:peer] && @data[:peer][:port]
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
# Returns the IP address of the remote host, as reported by the socket.
|
76
76
|
def ip
|
77
77
|
@data && @data[:peer] && @data[:peer][:ip]
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
# Returns the key itself, as reported by the remote host.
|
81
81
|
def key
|
82
82
|
@data && @data[:key]
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
# Tell Net::SSH to record this host and key in the known hosts file, so
|
86
86
|
# that subsequent connections will remember them.
|
87
87
|
def remember_host!
|
data/lib/net/ssh/key_factory.rb
CHANGED
@@ -5,7 +5,6 @@ require 'net/ssh/authentication/ed25519_loader'
|
|
5
5
|
|
6
6
|
module Net
|
7
7
|
module SSH
|
8
|
-
|
9
8
|
# A factory class for returning new Key classes. It is used for obtaining
|
10
9
|
# OpenSSL key instances via their SSH names, and for loading both public and
|
11
10
|
# private keys. It used used primarily by Net::SSH itself, internally, and
|
@@ -18,14 +17,14 @@ module Net
|
|
18
17
|
class KeyFactory
|
19
18
|
# Specifies the mapping of SSH names to OpenSSL key classes.
|
20
19
|
MAP = {
|
21
|
-
'dh'
|
22
|
-
'rsa'
|
23
|
-
'dsa'
|
20
|
+
'dh' => OpenSSL::PKey::DH,
|
21
|
+
'rsa' => OpenSSL::PKey::RSA,
|
22
|
+
'dsa' => OpenSSL::PKey::DSA,
|
24
23
|
'ecdsa' => OpenSSL::PKey::EC
|
25
24
|
}
|
26
25
|
MAP["ed25519"] = Net::SSH::Authentication::ED25519::PrivKey if defined? Net::SSH::Authentication::ED25519
|
27
26
|
|
28
|
-
class <<self
|
27
|
+
class << self
|
29
28
|
# Fetch an OpenSSL key instance by its SSH name. It will be a new,
|
30
29
|
# empty key of the given type.
|
31
30
|
def get(name)
|
@@ -37,7 +36,7 @@ module Net
|
|
37
36
|
# appropriately. The new key is returned. If the key itself is
|
38
37
|
# encrypted (requiring a passphrase to use), the user will be
|
39
38
|
# prompted to enter their password unless passphrase works.
|
40
|
-
def load_private_key(filename, passphrase=nil, ask_passphrase=true, prompt=Prompt.default)
|
39
|
+
def load_private_key(filename, passphrase = nil, ask_passphrase = true, prompt = Prompt.default)
|
41
40
|
data = File.read(File.expand_path(filename))
|
42
41
|
load_data_private_key(data, passphrase, ask_passphrase, filename, prompt)
|
43
42
|
end
|
@@ -47,7 +46,7 @@ module Net
|
|
47
46
|
# appropriately. The new key is returned. If the key itself is
|
48
47
|
# encrypted (requiring a passphrase to use), the user will be
|
49
48
|
# prompted to enter their password unless passphrase works.
|
50
|
-
def load_data_private_key(data, passphrase=nil, ask_passphrase=true, filename="", prompt=Prompt.default)
|
49
|
+
def load_data_private_key(data, passphrase = nil, ask_passphrase = true, filename = "", prompt = Prompt.default)
|
51
50
|
key_type = classify_key(data, filename)
|
52
51
|
|
53
52
|
encrypted_key = nil
|
@@ -87,7 +86,7 @@ module Net
|
|
87
86
|
# Loads a public key. It will correctly determine whether
|
88
87
|
# the file describes an RSA or DSA key, and will load it
|
89
88
|
# appropriately. The new public key is returned.
|
90
|
-
def load_data_public_key(data, filename="")
|
89
|
+
def load_data_public_key(data, filename = "")
|
91
90
|
fields = data.split(/ /)
|
92
91
|
|
93
92
|
blob = nil
|
data/lib/net/ssh/known_hosts.rb
CHANGED
@@ -1,11 +1,69 @@
|
|
1
1
|
require 'strscan'
|
2
2
|
require 'openssl'
|
3
3
|
require 'base64'
|
4
|
+
require 'delegate'
|
4
5
|
require 'net/ssh/buffer'
|
5
6
|
require 'net/ssh/authentication/ed25519_loader'
|
6
7
|
|
7
8
|
module Net
|
8
9
|
module SSH
|
10
|
+
module HostKeyEntries
|
11
|
+
# regular public key entry
|
12
|
+
class PubKey < Delegator
|
13
|
+
def initialize(key, comment: nil) # rubocop:disable Lint/MissingSuper
|
14
|
+
@key = key
|
15
|
+
@comment = comment
|
16
|
+
end
|
17
|
+
|
18
|
+
def ssh_type
|
19
|
+
@key.ssh_type
|
20
|
+
end
|
21
|
+
|
22
|
+
def ssh_types
|
23
|
+
[ssh_type]
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_blob
|
27
|
+
@key.to_blob
|
28
|
+
end
|
29
|
+
|
30
|
+
def __getobj__
|
31
|
+
Kernel.warn("Calling Net::SSH::Buffer methods on HostKeyEntries PubKey is deprecated")
|
32
|
+
@key
|
33
|
+
end
|
34
|
+
|
35
|
+
def matches_key?(server_key)
|
36
|
+
@key.ssh_type == server_key.ssh_type && @key.to_blob == server_key.to_blob
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# @cert-authority entry
|
41
|
+
class CertAuthority
|
42
|
+
def ssh_types
|
43
|
+
%w[
|
44
|
+
ecdsa-sha2-nistp256-cert-v01@openssh.com
|
45
|
+
ecdsa-sha2-nistp384-cert-v01@openssh.com
|
46
|
+
ecdsa-sha2-nistp521-cert-v01@openssh.com
|
47
|
+
ssh-ed25519-cert-v01@openssh.com
|
48
|
+
ssh-rsa-cert-v01@openssh.com
|
49
|
+
ssh-rsa-cert-v00@openssh.com
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(key, comment: nil)
|
54
|
+
@key = key
|
55
|
+
@comment = comment
|
56
|
+
end
|
57
|
+
|
58
|
+
def matches_key?(server_key)
|
59
|
+
if ssh_types.include?(server_key.ssh_type)
|
60
|
+
server_key.signature_valid? && (server_key.signature_key.to_blob == @key.to_blob)
|
61
|
+
else
|
62
|
+
false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
9
67
|
|
10
68
|
# Represents the result of a search in known hosts
|
11
69
|
# see search_for
|
@@ -48,10 +106,10 @@ module Net
|
|
48
106
|
|
49
107
|
SUPPORTED_TYPE.push('ssh-ed25519') if Net::SSH::Authentication::ED25519Loader::LOADED
|
50
108
|
|
51
|
-
class <<self
|
109
|
+
class << self
|
52
110
|
# Searches all known host files (see KnownHosts.hostfiles) for all keys
|
53
111
|
# of the given host. Returns an enumerable of keys found.
|
54
|
-
def search_for(host, options={})
|
112
|
+
def search_for(host, options = {})
|
55
113
|
HostKeys.new(search_in(hostfiles(options), host, options), host, self, options)
|
56
114
|
end
|
57
115
|
|
@@ -70,7 +128,7 @@ module Net
|
|
70
128
|
#
|
71
129
|
# If you only want the user known host files, you can pass :user as
|
72
130
|
# the second option.
|
73
|
-
def hostfiles(options, which
|
131
|
+
def hostfiles(options, which = :all)
|
74
132
|
files = []
|
75
133
|
|
76
134
|
files += Array(options[:user_known_hosts_file] || %w[~/.ssh/known_hosts ~/.ssh/known_hosts2]) if which == :all || which == :user
|
@@ -85,14 +143,12 @@ module Net
|
|
85
143
|
# Looks in all user known host files (see KnownHosts.hostfiles) and tries to
|
86
144
|
# add an entry for the given host and key to the first file it is able
|
87
145
|
# to.
|
88
|
-
def add(host, key, options={})
|
146
|
+
def add(host, key, options = {})
|
89
147
|
hostfiles(options, :user).each do |file|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
# try the next hostfile
|
95
|
-
end
|
148
|
+
KnownHosts.new(file).add(host, key)
|
149
|
+
return
|
150
|
+
rescue SystemCallError
|
151
|
+
# try the next hostfile
|
96
152
|
end
|
97
153
|
end
|
98
154
|
end
|
@@ -130,7 +186,13 @@ module Net
|
|
130
186
|
|
131
187
|
File.open(source) do |file|
|
132
188
|
file.each_line do |line|
|
133
|
-
|
189
|
+
if line.start_with?('@')
|
190
|
+
marker, hosts, type, key_content, comment = line.split(' ')
|
191
|
+
else
|
192
|
+
marker = nil
|
193
|
+
hosts, type, key_content, comment = line.split(' ')
|
194
|
+
end
|
195
|
+
|
134
196
|
# Skip empty line or one that is commented
|
135
197
|
next if hosts.nil? || hosts.start_with?('#')
|
136
198
|
|
@@ -145,7 +207,14 @@ module Net
|
|
145
207
|
next unless found
|
146
208
|
|
147
209
|
blob = key_content.unpack("m*").first
|
148
|
-
|
210
|
+
raw_key = Net::SSH::Buffer.new(blob).read_key
|
211
|
+
|
212
|
+
keys <<
|
213
|
+
if marker == "@cert-authority"
|
214
|
+
HostKeyEntries::CertAuthority.new(raw_key, comment: comment)
|
215
|
+
else
|
216
|
+
HostKeyEntries::PubKey.new(raw_key, comment: comment)
|
217
|
+
end
|
149
218
|
end
|
150
219
|
end
|
151
220
|
|
@@ -155,11 +224,11 @@ module Net
|
|
155
224
|
def match(host, pattern)
|
156
225
|
if pattern.include?('*') || pattern.include?('?')
|
157
226
|
# see man 8 sshd for pattern details
|
158
|
-
pattern_regexp = pattern.split('*').map do |x|
|
159
|
-
x.split('?').map do |y|
|
227
|
+
pattern_regexp = pattern.split('*', -1).map do |x|
|
228
|
+
x.split('?', -1).map do |y|
|
160
229
|
Regexp.escape(y)
|
161
230
|
end.join('.')
|
162
|
-
end.join('
|
231
|
+
end.join('.*')
|
163
232
|
|
164
233
|
host =~ Regexp.new("\\A#{pattern_regexp}\\z")
|
165
234
|
else
|
data/lib/net/ssh/loggable.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
module Net
|
1
|
+
module Net
|
2
2
|
module SSH
|
3
|
-
|
4
3
|
# A simple module to make logging easier to deal with. It assumes that the
|
5
4
|
# logger instance (if not nil) quacks like a Logger object (in Ruby's
|
6
5
|
# standard library). Although used primarily internally by Net::SSH, it
|
@@ -19,39 +18,39 @@ module Net
|
|
19
18
|
# The logger instance that will be used to log messages. If nil, nothing
|
20
19
|
# will be logged.
|
21
20
|
attr_accessor :logger
|
22
|
-
|
21
|
+
|
23
22
|
# Displays the result of yielding if the log level is Logger::DEBUG or
|
24
23
|
# greater.
|
25
24
|
def debug
|
26
25
|
logger.add(Logger::DEBUG, nil, facility) { yield } if logger && logger.debug?
|
27
26
|
end
|
28
|
-
|
27
|
+
|
29
28
|
# Displays the result of yielding if the log level is Logger::INFO or
|
30
29
|
# greater.
|
31
30
|
def info
|
32
31
|
logger.add(Logger::INFO, nil, facility) { yield } if logger && logger.info?
|
33
32
|
end
|
34
|
-
|
33
|
+
|
35
34
|
# Displays the result of yielding if the log level is Logger::WARN or
|
36
35
|
# greater. (Called lwarn to avoid shadowing with Kernel#warn.)
|
37
36
|
def lwarn
|
38
37
|
logger.add(Logger::WARN, nil, facility) { yield } if logger && logger.warn?
|
39
38
|
end
|
40
|
-
|
39
|
+
|
41
40
|
# Displays the result of yielding if the log level is Logger:ERROR or
|
42
41
|
# greater.
|
43
42
|
def error
|
44
43
|
logger.add(Logger::ERROR, nil, facility) { yield } if logger && logger.error?
|
45
44
|
end
|
46
|
-
|
45
|
+
|
47
46
|
# Displays the result of yielding if the log level is Logger::FATAL or
|
48
47
|
# greater.
|
49
48
|
def fatal
|
50
49
|
logger.add(Logger::FATAL, nil, facility) { yield } if logger && logger.fatal?
|
51
50
|
end
|
52
|
-
|
51
|
+
|
53
52
|
private
|
54
|
-
|
53
|
+
|
55
54
|
# Sets the "facility" value, used for reporting where a log message
|
56
55
|
# originates. It defaults to the name of class with the object_id
|
57
56
|
# appended.
|
data/lib/net/ssh/packet.rb
CHANGED
@@ -5,7 +5,6 @@ require 'net/ssh/connection/constants'
|
|
5
5
|
|
6
6
|
module Net
|
7
7
|
module SSH
|
8
|
-
|
9
8
|
# A specialization of Buffer that knows the format of certain common
|
10
9
|
# packet types. It auto-parses those packet types, and allows them to
|
11
10
|
# be accessed via the #[] accessor.
|
@@ -85,6 +84,7 @@ module Net
|
|
85
84
|
def [](name)
|
86
85
|
name = name.to_sym
|
87
86
|
raise ArgumentError, "no such element #{name}" unless @named_elements.key?(name)
|
87
|
+
|
88
88
|
@named_elements[name]
|
89
89
|
end
|
90
90
|
|
data/lib/net/ssh/prompt.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'io/console'
|
2
2
|
|
3
|
-
module Net
|
3
|
+
module Net
|
4
4
|
module SSH
|
5
|
-
|
6
5
|
# Default prompt implementation, called for asking password from user.
|
7
6
|
# It will never be instantiated directly, but will instead be created for
|
8
7
|
# you automatically.
|
@@ -13,8 +12,8 @@ module Net
|
|
13
12
|
#
|
14
13
|
# prompter = options[:password_prompt].start({type:'password'})
|
15
14
|
# while !ok && max_retries < 3
|
16
|
-
# user = prompter.ask("user: ",
|
17
|
-
# password = prompter.ask("password: ",
|
15
|
+
# user = prompter.ask("user: ", true)
|
16
|
+
# password = prompter.ask("password: ", false)
|
18
17
|
# ok = send(user, password)
|
19
18
|
# prompter.sucess if ok
|
20
19
|
# end
|
@@ -24,9 +23,9 @@ module Net
|
|
24
23
|
def self.default(options = {})
|
25
24
|
@default ||= new(options)
|
26
25
|
end
|
27
|
-
|
26
|
+
|
28
27
|
def initialize(options = {}); end
|
29
|
-
|
28
|
+
|
30
29
|
# default prompt object implementation. More sophisticated implemenetations
|
31
30
|
# might implement caching.
|
32
31
|
class Prompter
|
@@ -36,22 +35,22 @@ module Net
|
|
36
35
|
$stdout.puts(info[:instruction]) unless info[:instruction].empty?
|
37
36
|
end
|
38
37
|
end
|
39
|
-
|
38
|
+
|
40
39
|
# ask input from user, a prompter might ask for multiple inputs
|
41
40
|
# (like user and password) in a single session.
|
42
|
-
def ask(prompt, echo=true)
|
41
|
+
def ask(prompt, echo = true)
|
43
42
|
$stdout.print(prompt)
|
44
43
|
$stdout.flush
|
45
44
|
ret = $stdin.noecho(&:gets).chomp
|
46
45
|
$stdout.print("\n")
|
47
46
|
ret
|
48
47
|
end
|
49
|
-
|
48
|
+
|
50
49
|
# success method will be called when the password was accepted
|
51
50
|
# It's a good time to save password asked to a cache.
|
52
51
|
def success; end
|
53
52
|
end
|
54
|
-
|
53
|
+
|
55
54
|
# start password session. Multiple questions might be asked multiple times
|
56
55
|
# on the returned object. Info hash tries to uniquely identify the password
|
57
56
|
# session, so caching implementations can save passwords properly.
|
@@ -59,6 +58,5 @@ module Net
|
|
59
58
|
Prompter.new(info)
|
60
59
|
end
|
61
60
|
end
|
62
|
-
|
63
61
|
end
|
64
62
|
end
|
@@ -5,7 +5,6 @@ require 'net/ssh/proxy/errors'
|
|
5
5
|
module Net
|
6
6
|
module SSH
|
7
7
|
module Proxy
|
8
|
-
|
9
8
|
# An implementation of a command proxy. To use it, instantiate it,
|
10
9
|
# then pass the instantiated object via the :proxy key to
|
11
10
|
# Net::SSH.start:
|
@@ -105,6 +104,7 @@ module Net
|
|
105
104
|
if IO.select([self], nil, [self], timeout_in_seconds) == nil
|
106
105
|
raise "Unexpected spurious read wakeup"
|
107
106
|
end
|
107
|
+
|
108
108
|
retry
|
109
109
|
end
|
110
110
|
result
|
data/lib/net/ssh/proxy/errors.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require 'net/ssh/errors'
|
2
2
|
|
3
|
-
module Net
|
4
|
-
module SSH
|
3
|
+
module Net
|
4
|
+
module SSH
|
5
5
|
module Proxy
|
6
|
-
|
7
6
|
# A general exception class for all Proxy errors.
|
8
7
|
class Error < Net::SSH::Exception; end
|
9
8
|
|
@@ -12,7 +11,6 @@ module Net
|
|
12
11
|
|
13
12
|
# Used when the server doesn't recognize the user's credentials.
|
14
13
|
class UnauthorizedError < Error; end
|
15
|
-
|
16
14
|
end
|
17
15
|
end
|
18
16
|
end
|