net-ssh-backports 6.3.0.backports

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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