net-ssh-backports 6.3.0.backports

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +93 -0
  3. data/.gitignore +13 -0
  4. data/.rubocop.yml +21 -0
  5. data/.rubocop_todo.yml +1074 -0
  6. data/.travis.yml +51 -0
  7. data/CHANGES.txt +698 -0
  8. data/Gemfile +13 -0
  9. data/Gemfile.noed25519 +12 -0
  10. data/ISSUE_TEMPLATE.md +30 -0
  11. data/LICENSE.txt +19 -0
  12. data/Manifest +132 -0
  13. data/README.md +287 -0
  14. data/Rakefile +105 -0
  15. data/THANKS.txt +110 -0
  16. data/appveyor.yml +58 -0
  17. data/lib/net/ssh/authentication/agent.rb +284 -0
  18. data/lib/net/ssh/authentication/certificate.rb +183 -0
  19. data/lib/net/ssh/authentication/constants.rb +20 -0
  20. data/lib/net/ssh/authentication/ed25519.rb +185 -0
  21. data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  22. data/lib/net/ssh/authentication/key_manager.rb +297 -0
  23. data/lib/net/ssh/authentication/methods/abstract.rb +69 -0
  24. data/lib/net/ssh/authentication/methods/hostbased.rb +72 -0
  25. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +77 -0
  26. data/lib/net/ssh/authentication/methods/none.rb +34 -0
  27. data/lib/net/ssh/authentication/methods/password.rb +80 -0
  28. data/lib/net/ssh/authentication/methods/publickey.rb +95 -0
  29. data/lib/net/ssh/authentication/pageant.rb +497 -0
  30. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  31. data/lib/net/ssh/authentication/session.rb +163 -0
  32. data/lib/net/ssh/buffer.rb +434 -0
  33. data/lib/net/ssh/buffered_io.rb +202 -0
  34. data/lib/net/ssh/config.rb +406 -0
  35. data/lib/net/ssh/connection/channel.rb +695 -0
  36. data/lib/net/ssh/connection/constants.rb +33 -0
  37. data/lib/net/ssh/connection/event_loop.rb +123 -0
  38. data/lib/net/ssh/connection/keepalive.rb +59 -0
  39. data/lib/net/ssh/connection/session.rb +712 -0
  40. data/lib/net/ssh/connection/term.rb +180 -0
  41. data/lib/net/ssh/errors.rb +106 -0
  42. data/lib/net/ssh/key_factory.rb +218 -0
  43. data/lib/net/ssh/known_hosts.rb +264 -0
  44. data/lib/net/ssh/loggable.rb +62 -0
  45. data/lib/net/ssh/packet.rb +106 -0
  46. data/lib/net/ssh/prompt.rb +62 -0
  47. data/lib/net/ssh/proxy/command.rb +123 -0
  48. data/lib/net/ssh/proxy/errors.rb +16 -0
  49. data/lib/net/ssh/proxy/http.rb +98 -0
  50. data/lib/net/ssh/proxy/https.rb +50 -0
  51. data/lib/net/ssh/proxy/jump.rb +54 -0
  52. data/lib/net/ssh/proxy/socks4.rb +67 -0
  53. data/lib/net/ssh/proxy/socks5.rb +140 -0
  54. data/lib/net/ssh/service/forward.rb +426 -0
  55. data/lib/net/ssh/test/channel.rb +147 -0
  56. data/lib/net/ssh/test/extensions.rb +173 -0
  57. data/lib/net/ssh/test/kex.rb +46 -0
  58. data/lib/net/ssh/test/local_packet.rb +53 -0
  59. data/lib/net/ssh/test/packet.rb +101 -0
  60. data/lib/net/ssh/test/remote_packet.rb +40 -0
  61. data/lib/net/ssh/test/script.rb +180 -0
  62. data/lib/net/ssh/test/socket.rb +65 -0
  63. data/lib/net/ssh/test.rb +94 -0
  64. data/lib/net/ssh/transport/algorithms.rb +502 -0
  65. data/lib/net/ssh/transport/cipher_factory.rb +103 -0
  66. data/lib/net/ssh/transport/constants.rb +40 -0
  67. data/lib/net/ssh/transport/ctr.rb +115 -0
  68. data/lib/net/ssh/transport/hmac/abstract.rb +97 -0
  69. data/lib/net/ssh/transport/hmac/md5.rb +10 -0
  70. data/lib/net/ssh/transport/hmac/md5_96.rb +9 -0
  71. data/lib/net/ssh/transport/hmac/none.rb +13 -0
  72. data/lib/net/ssh/transport/hmac/ripemd160.rb +11 -0
  73. data/lib/net/ssh/transport/hmac/sha1.rb +11 -0
  74. data/lib/net/ssh/transport/hmac/sha1_96.rb +9 -0
  75. data/lib/net/ssh/transport/hmac/sha2_256.rb +11 -0
  76. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +9 -0
  77. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  78. data/lib/net/ssh/transport/hmac/sha2_512.rb +11 -0
  79. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +9 -0
  80. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  81. data/lib/net/ssh/transport/hmac.rb +47 -0
  82. data/lib/net/ssh/transport/identity_cipher.rb +57 -0
  83. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  84. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  85. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  86. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  87. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +37 -0
  88. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  89. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +122 -0
  90. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +72 -0
  91. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +11 -0
  92. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +39 -0
  93. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +21 -0
  94. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +21 -0
  95. data/lib/net/ssh/transport/kex.rb +31 -0
  96. data/lib/net/ssh/transport/key_expander.rb +30 -0
  97. data/lib/net/ssh/transport/openssl.rb +253 -0
  98. data/lib/net/ssh/transport/packet_stream.rb +280 -0
  99. data/lib/net/ssh/transport/server_version.rb +77 -0
  100. data/lib/net/ssh/transport/session.rb +354 -0
  101. data/lib/net/ssh/transport/state.rb +208 -0
  102. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  103. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  104. data/lib/net/ssh/verifiers/always.rb +58 -0
  105. data/lib/net/ssh/verifiers/never.rb +19 -0
  106. data/lib/net/ssh/version.rb +68 -0
  107. data/lib/net/ssh.rb +330 -0
  108. data/net-ssh-public_cert.pem +20 -0
  109. data/net-ssh.gemspec +44 -0
  110. data/support/ssh_tunnel_bug.rb +65 -0
  111. metadata +271 -0
@@ -0,0 +1,180 @@
1
+ module Net
2
+ module SSH
3
+ module Connection
4
+ # These constants are used when requesting a pseudo-terminal (via
5
+ # Net::SSH::Connection::Channel#request_pty). The descriptions for each are
6
+ # taken directly from RFC 4254 ("The Secure Shell (SSH) Connection Protocol"),
7
+ # http://tools.ietf.org/html/rfc4254.
8
+ module Term
9
+ # Interrupt character; 255 if none. Similarly for the other characters.
10
+ # Not all of these characters are supported on all systems.
11
+ VINTR = 1
12
+
13
+ # The quit character (sends SIGQUIT signal on POSIX systems).
14
+ VQUIT = 2
15
+
16
+ # Erase the character to left of the cursor.
17
+ VERASE = 3
18
+
19
+ # Kill the current input line.
20
+ VKILL = 4
21
+
22
+ # End-of-file character (sends EOF from the terminal).
23
+ VEOF = 5
24
+
25
+ # End-of-line character in addition to carriage return and/or linefeed.
26
+ VEOL = 6
27
+
28
+ # Additional end-of-line character.
29
+ VEOL2 = 7
30
+
31
+ # Continues paused output (normally control-Q).
32
+ VSTART = 8
33
+
34
+ # Pauses output (normally control-S).
35
+ VSTOP = 9
36
+
37
+ # Suspends the current program.
38
+ VSUSP = 10
39
+
40
+ # Another suspend character.
41
+ VDSUSP = 11
42
+
43
+ # Reprints the current input line.
44
+ VREPRINT = 12
45
+
46
+ # Erases a word left of cursor.
47
+ VWERASE = 13
48
+
49
+ # Enter the next character typed literally, even if it is a special
50
+ # character.
51
+ VLNEXT = 14
52
+
53
+ # Character to flush output.
54
+ VFLUSH = 15
55
+
56
+ # Switch to a different shell layer.
57
+ VSWITCH = 16
58
+
59
+ # Prints system status line (load, command, pid, etc).
60
+ VSTATUS = 17
61
+
62
+ # Toggles the flushing of terminal output.
63
+ VDISCARD = 18
64
+
65
+ # The ignore parity flag. The parameter SHOULD be 0 if this flag is FALSE,
66
+ # and 1 if it is TRUE.
67
+ IGNPAR = 30
68
+
69
+ # Mark parity and framing errors.
70
+ PARMRK = 31
71
+
72
+ # Enable checking of parity errors.
73
+ INPCK = 32
74
+
75
+ # Strip 8th bit off characters.
76
+ ISTRIP = 33
77
+
78
+ # Map NL into CR on input.
79
+ INCLR = 34
80
+
81
+ # Ignore CR on input.
82
+ IGNCR = 35
83
+
84
+ # Map CR to NL on input.
85
+ ICRNL = 36
86
+
87
+ # Translate uppercase characters to lowercase.
88
+ IUCLC = 37
89
+
90
+ # Enable output flow control.
91
+ IXON = 38
92
+
93
+ # Any char will restart after stop.
94
+ IXANY = 39
95
+
96
+ # Enable input flow control.
97
+ IXOFF = 40
98
+
99
+ # Ring bell on input queue full.
100
+ IMAXBEL = 41
101
+
102
+ # Enable signals INTR, QUIT, [D]SUSP.
103
+ ISIG = 50
104
+
105
+ # Canonicalize input lines.
106
+ ICANON = 51
107
+
108
+ # Enable input and output of uppercase characters by preceding their
109
+ # lowercase equivalents with "\".
110
+ XCASE = 52
111
+
112
+ # Enable echoing.
113
+ ECHO = 53
114
+
115
+ # Visually erase chars.
116
+ ECHOE = 54
117
+
118
+ # Kill character discards current line.
119
+ ECHOK = 55
120
+
121
+ # Echo NL even if ECHO is off.
122
+ ECHONL = 56
123
+
124
+ # Don't flush after interrupt.
125
+ NOFLSH = 57
126
+
127
+ # Stop background jobs from output.
128
+ TOSTOP = 58
129
+
130
+ # Enable extensions.
131
+ IEXTEN = 59
132
+
133
+ # Echo control characters as ^(Char).
134
+ ECHOCTL = 60
135
+
136
+ # Visual erase for line kill.
137
+ ECHOKE = 61
138
+
139
+ # Retype pending input.
140
+ PENDIN = 62
141
+
142
+ # Enable output processing.
143
+ OPOST = 70
144
+
145
+ # Convert lowercase to uppercase.
146
+ OLCUC = 71
147
+
148
+ # Map NL to CR-NL.
149
+ ONLCR = 72
150
+
151
+ # Translate carriage return to newline (output).
152
+ OCRNL = 73
153
+
154
+ # Translate newline to carriage return-newline (output).
155
+ ONOCR = 74
156
+
157
+ # Newline performs a carriage return (output).
158
+ ONLRET = 75
159
+
160
+ # 7 bit mode.
161
+ CS7 = 90
162
+
163
+ # 8 bit mode.
164
+ CS8 = 91
165
+
166
+ # Parity enable.
167
+ PARENB = 92
168
+
169
+ # Odd parity, else even.
170
+ PARODD = 93
171
+
172
+ # Specifies the input baud rate in bits per second.
173
+ TTY_OP_ISPEED = 128
174
+
175
+ # Specifies the output baud rate in bits per second.
176
+ TTY_OP_OSPEED = 129
177
+ end
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,106 @@
1
+ module Net
2
+ module SSH
3
+ # A general exception class, to act as the ancestor of all other Net::SSH
4
+ # exception classes.
5
+ class Exception < ::RuntimeError; end
6
+
7
+ # This exception is raised when authentication fails (whether it be
8
+ # public key authentication, password authentication, or whatever).
9
+ class AuthenticationFailed < Net::SSH::Exception; end
10
+
11
+ # This exception is raised when a connection attempt times out.
12
+ class ConnectionTimeout < Net::SSH::Exception; end
13
+
14
+ # This exception is raised when the remote host has disconnected
15
+ # unexpectedly.
16
+ class Disconnect < Net::SSH::Exception; end
17
+
18
+ # This exception is raised when the remote host has disconnected/
19
+ # timeouted unexpectedly.
20
+ class Timeout < Disconnect; end
21
+
22
+ # This exception is primarily used internally, but if you have a channel
23
+ # request handler (see Net::SSH::Connection::Channel#on_request) that you
24
+ # want to fail in such a way that the server knows it failed, you can
25
+ # raise this exception in the handler and Net::SSH will translate that into
26
+ # a "channel failure" message.
27
+ class ChannelRequestFailed < Net::SSH::Exception; end
28
+
29
+ # This is exception is primarily used internally, but if you have a channel
30
+ # open handler (see Net::SSH::Connection::Session#on_open_channel) and you
31
+ # want to fail in such a way that the server knows it failed, you can
32
+ # raise this exception in the handler and Net::SSH will translate that into
33
+ # a "channel open failed" message.
34
+ class ChannelOpenFailed < Net::SSH::Exception
35
+ attr_reader :code, :reason
36
+
37
+ def initialize(code, reason)
38
+ @code, @reason = code, reason
39
+ super "#{reason} (#{code})"
40
+ end
41
+ end
42
+
43
+ # Base class for host key exceptions. When rescuing this exception, you can
44
+ # inspect the key fingerprint and, if you want to proceed anyway, simply call
45
+ # the remember_host! method on the exception, and then retry.
46
+ class HostKeyError < Net::SSH::Exception
47
+ # the callback to use when #remember_host! is called
48
+ attr_writer :callback #:nodoc:
49
+
50
+ # situation-specific data describing the host (see #host, #port, etc.)
51
+ attr_writer :data #:nodoc:
52
+
53
+ # An accessor for getting at the data that was used to look up the host
54
+ # (see also #fingerprint, #host, #port, #ip, and #key).
55
+ def [](key)
56
+ @data && @data[key]
57
+ end
58
+
59
+ # Returns the fingerprint of the key for the host, which either was not
60
+ # found or did not match.
61
+ def fingerprint
62
+ @data && @data[:fingerprint]
63
+ end
64
+
65
+ # Returns the host name for the remote host, as reported by the socket.
66
+ def host
67
+ @data && @data[:peer] && @data[:peer][:host]
68
+ end
69
+
70
+ # Returns the port number for the remote host, as reported by the socket.
71
+ def port
72
+ @data && @data[:peer] && @data[:peer][:port]
73
+ end
74
+
75
+ # Returns the IP address of the remote host, as reported by the socket.
76
+ def ip
77
+ @data && @data[:peer] && @data[:peer][:ip]
78
+ end
79
+
80
+ # Returns the key itself, as reported by the remote host.
81
+ def key
82
+ @data && @data[:key]
83
+ end
84
+
85
+ # Tell Net::SSH to record this host and key in the known hosts file, so
86
+ # that subsequent connections will remember them.
87
+ def remember_host!
88
+ @callback.call
89
+ end
90
+ end
91
+
92
+ # Raised when the cached key for a particular host does not match the
93
+ # key given by the host, which can be indicative of a man-in-the-middle
94
+ # attack. When rescuing this exception, you can inspect the key fingerprint
95
+ # and, if you want to proceed anyway, simply call the remember_host!
96
+ # method on the exception, and then retry.
97
+ class HostKeyMismatch < HostKeyError; end
98
+
99
+ # Raised when there is no cached key for a particular host, which probably
100
+ # means that the host has simply not been seen before.
101
+ # When rescuing this exception, you can inspect the key fingerprint and, if
102
+ # you want to proceed anyway, simply call the remember_host! method on the
103
+ # exception, and then retry.
104
+ class HostKeyUnknown < HostKeyError; end
105
+ end
106
+ end
@@ -0,0 +1,218 @@
1
+ require 'net/ssh/transport/openssl'
2
+ require 'net/ssh/prompt'
3
+
4
+ require 'net/ssh/authentication/ed25519_loader'
5
+
6
+ module Net
7
+ module SSH
8
+ # A factory class for returning new Key classes. It is used for obtaining
9
+ # OpenSSL key instances via their SSH names, and for loading both public and
10
+ # private keys. It used used primarily by Net::SSH itself, internally, and
11
+ # will rarely (if ever) be directly used by consumers of the library.
12
+ #
13
+ # klass = Net::SSH::KeyFactory.get("rsa")
14
+ # assert klass.is_a?(OpenSSL::PKey::RSA)
15
+ #
16
+ # key = Net::SSH::KeyFactory.load_public_key("~/.ssh/id_dsa.pub")
17
+ class KeyFactory
18
+ # Specifies the mapping of SSH names to OpenSSL key classes.
19
+ MAP = {
20
+ 'dh' => OpenSSL::PKey::DH,
21
+ 'rsa' => OpenSSL::PKey::RSA,
22
+ 'dsa' => OpenSSL::PKey::DSA,
23
+ 'ecdsa' => OpenSSL::PKey::EC
24
+ }
25
+ MAP["ed25519"] = Net::SSH::Authentication::ED25519::PrivKey if defined? Net::SSH::Authentication::ED25519
26
+
27
+ class <<self
28
+ # Fetch an OpenSSL key instance by its SSH name. It will be a new,
29
+ # empty key of the given type.
30
+ def get(name)
31
+ MAP.fetch(name).new
32
+ end
33
+
34
+ # Loads a private key from a file. It will correctly determine
35
+ # whether the file describes an RSA or DSA key, and will load it
36
+ # appropriately. The new key is returned. If the key itself is
37
+ # encrypted (requiring a passphrase to use), the user will be
38
+ # prompted to enter their password unless passphrase works.
39
+ def load_private_key(filename, passphrase=nil, ask_passphrase=true, prompt=Prompt.default)
40
+ data = File.read(File.expand_path(filename))
41
+ load_data_private_key(data, passphrase, ask_passphrase, filename, prompt)
42
+ end
43
+
44
+ # Loads a private key. It will correctly determine
45
+ # whether the file describes an RSA or DSA key, and will load it
46
+ # appropriately. The new key is returned. If the key itself is
47
+ # encrypted (requiring a passphrase to use), the user will be
48
+ # prompted to enter their password unless passphrase works.
49
+ def load_data_private_key(data, passphrase=nil, ask_passphrase=true, filename="", prompt=Prompt.default)
50
+ key_type = classify_key(data, filename)
51
+
52
+ encrypted_key = nil
53
+ tries = 0
54
+
55
+ prompter = nil
56
+ result =
57
+ begin
58
+ key_type.read(data, passphrase || 'invalid')
59
+ rescue *key_type.error_classes => e
60
+ encrypted_key = !!key_type.encrypted_key?(data, e) if encrypted_key.nil?
61
+ if encrypted_key && ask_passphrase
62
+ tries += 1
63
+ if tries <= 3
64
+ prompter ||= prompt.start(type: 'private_key', filename: filename, sha: Digest::SHA256.digest(data))
65
+ passphrase = prompter.ask("Enter passphrase for #{filename}:", false)
66
+ retry
67
+ else
68
+ raise
69
+ end
70
+ else
71
+ raise
72
+ end
73
+ end
74
+ prompter.success if prompter
75
+ result
76
+ end
77
+
78
+ # Loads a public key from a file. It will correctly determine whether
79
+ # the file describes an RSA or DSA key, and will load it
80
+ # appropriately. The new public key is returned.
81
+ def load_public_key(filename)
82
+ data = File.read(File.expand_path(filename))
83
+ load_data_public_key(data, filename)
84
+ end
85
+
86
+ # Loads a public key. It will correctly determine whether
87
+ # the file describes an RSA or DSA key, and will load it
88
+ # appropriately. The new public key is returned.
89
+ def load_data_public_key(data, filename="")
90
+ fields = data.split(/ /)
91
+
92
+ blob = nil
93
+ begin
94
+ blob = fields.shift
95
+ end while !blob.nil? && !/^(ssh-(rsa|dss|ed25519)|ecdsa-sha2-nistp\d+)(-cert-v01@openssh\.com)?$/.match(blob)
96
+ blob = fields.shift
97
+
98
+ raise Net::SSH::Exception, "public key at #{filename} is not valid" if blob.nil?
99
+
100
+ blob = blob.unpack("m*").first
101
+ reader = Net::SSH::Buffer.new(blob)
102
+ reader.read_key or raise OpenSSL::PKey::PKeyError, "not a public key #{filename.inspect}"
103
+ end
104
+
105
+ private
106
+
107
+ # rubocop:disable Style/Documentation, Lint/DuplicateMethods
108
+ class KeyType
109
+ def self.read(key_data, passphrase)
110
+ raise Exception, "TODO subclasses should implement read"
111
+ end
112
+
113
+ def self.error_classes
114
+ raise Exception, "TODO subclasses should implement read"
115
+ end
116
+
117
+ def self.encrypted_key?(data, error)
118
+ raise Exception, "TODO subclasses should implement is_encrypted_key"
119
+ end
120
+ end
121
+
122
+ class OpenSSHPrivateKeyType < KeyType
123
+ def self.read(key_data, passphrase)
124
+ Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader.read(key_data, passphrase)
125
+ end
126
+
127
+ def self.error_classes
128
+ [Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader::DecryptError]
129
+ end
130
+
131
+ def self.encrypted_key?(key_data, decode_error)
132
+ decode_error.is_a?(Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader::DecryptError) && decode_error.encrypted_key?
133
+ end
134
+ end
135
+
136
+ class OpenSSLKeyTypeBase < KeyType
137
+ def self.open_ssl_class
138
+ raise Exception, "TODO: subclasses should implement"
139
+ end
140
+
141
+ def self.read(key_data, passphrase)
142
+ open_ssl_class.new(key_data, passphrase)
143
+ end
144
+
145
+ def self.encrypted_key?(key_data, error)
146
+ key_data.match(/ENCRYPTED/)
147
+ end
148
+ end
149
+
150
+ class OpenSSLPKeyType < OpenSSLKeyTypeBase
151
+ def self.read(key_data, passphrase)
152
+ open_ssl_class.read(key_data, passphrase)
153
+ end
154
+
155
+ def self.open_ssl_class
156
+ OpenSSL::PKey
157
+ end
158
+
159
+ def self.error_classes
160
+ [ArgumentError, OpenSSL::PKey::PKeyError]
161
+ end
162
+ end
163
+
164
+ class OpenSSLDSAKeyType < OpenSSLKeyTypeBase
165
+ def self.open_ssl_class
166
+ OpenSSL::PKey::DSA
167
+ end
168
+
169
+ def self.error_classes
170
+ [OpenSSL::PKey::DSAError]
171
+ end
172
+ end
173
+
174
+ class OpenSSLRSAKeyType < OpenSSLKeyTypeBase
175
+ def self.open_ssl_class
176
+ OpenSSL::PKey::RSA
177
+ end
178
+
179
+ def self.error_classes
180
+ [OpenSSL::PKey::RSAError]
181
+ end
182
+ end
183
+
184
+ class OpenSSLECKeyType < OpenSSLKeyTypeBase
185
+ def self.open_ssl_class
186
+ OpenSSL::PKey::EC
187
+ end
188
+
189
+ def self.error_classes
190
+ [OpenSSL::PKey::ECError]
191
+ end
192
+ end
193
+ # rubocop:enable Style/Documentation, Lint/DuplicateMethods
194
+
195
+ # Determine whether the file describes an RSA or DSA key, and return how load it
196
+ # appropriately.
197
+ def classify_key(data, filename)
198
+ if data.match(/-----BEGIN OPENSSH PRIVATE KEY-----/)
199
+ Net::SSH::Authentication::ED25519Loader.raiseUnlessLoaded("OpenSSH keys only supported if ED25519 is available")
200
+ return OpenSSHPrivateKeyType
201
+ elsif OpenSSL::PKey.respond_to?(:read)
202
+ return OpenSSLPKeyType
203
+ elsif data.match(/-----BEGIN DSA PRIVATE KEY-----/)
204
+ return OpenSSLDSAKeyType
205
+ elsif data.match(/-----BEGIN RSA PRIVATE KEY-----/)
206
+ return OpenSSLRSAKeyType
207
+ elsif data.match(/-----BEGIN EC PRIVATE KEY-----/)
208
+ return OpenSSLECKeyType
209
+ elsif data.match(/-----BEGIN (.+) PRIVATE KEY-----/)
210
+ raise OpenSSL::PKey::PKeyError, "not a supported key type '#{$1}'"
211
+ else
212
+ raise OpenSSL::PKey::PKeyError, "not a private key (#{filename})"
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end