net-ssh 5.0.2 → 7.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/config/rubocop_linter_action.yml +4 -0
  5. data/.github/workflows/ci-with-docker.yml +44 -0
  6. data/.github/workflows/ci.yml +87 -0
  7. data/.github/workflows/rubocop.yml +13 -0
  8. data/.gitignore +3 -0
  9. data/.rubocop.yml +19 -2
  10. data/.rubocop_todo.yml +623 -511
  11. data/CHANGES.txt +76 -0
  12. data/Dockerfile +27 -0
  13. data/Dockerfile.openssl3 +17 -0
  14. data/Gemfile +2 -0
  15. data/Gemfile.noed25519 +2 -0
  16. data/Manifest +0 -1
  17. data/README.md +293 -0
  18. data/Rakefile +6 -2
  19. data/appveyor.yml +4 -2
  20. data/docker-compose.yml +23 -0
  21. data/lib/net/ssh/authentication/agent.rb +36 -14
  22. data/lib/net/ssh/authentication/certificate.rb +19 -7
  23. data/lib/net/ssh/authentication/constants.rb +0 -1
  24. data/lib/net/ssh/authentication/ed25519.rb +83 -50
  25. data/lib/net/ssh/authentication/ed25519_loader.rb +5 -8
  26. data/lib/net/ssh/authentication/key_manager.rb +74 -33
  27. data/lib/net/ssh/authentication/methods/abstract.rb +12 -3
  28. data/lib/net/ssh/authentication/methods/hostbased.rb +3 -5
  29. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +5 -3
  30. data/lib/net/ssh/authentication/methods/none.rb +6 -9
  31. data/lib/net/ssh/authentication/methods/password.rb +2 -3
  32. data/lib/net/ssh/authentication/methods/publickey.rb +58 -16
  33. data/lib/net/ssh/authentication/pageant.rb +97 -97
  34. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +2 -3
  35. data/lib/net/ssh/authentication/session.rb +27 -23
  36. data/lib/net/ssh/buffer.rb +91 -40
  37. data/lib/net/ssh/buffered_io.rb +24 -26
  38. data/lib/net/ssh/config.rb +99 -53
  39. data/lib/net/ssh/connection/channel.rb +101 -87
  40. data/lib/net/ssh/connection/constants.rb +0 -4
  41. data/lib/net/ssh/connection/event_loop.rb +30 -25
  42. data/lib/net/ssh/connection/keepalive.rb +12 -12
  43. data/lib/net/ssh/connection/session.rb +115 -111
  44. data/lib/net/ssh/connection/term.rb +56 -58
  45. data/lib/net/ssh/errors.rb +12 -12
  46. data/lib/net/ssh/key_factory.rb +108 -22
  47. data/lib/net/ssh/known_hosts.rb +120 -36
  48. data/lib/net/ssh/loggable.rb +10 -11
  49. data/lib/net/ssh/packet.rb +1 -1
  50. data/lib/net/ssh/prompt.rb +9 -11
  51. data/lib/net/ssh/proxy/command.rb +1 -2
  52. data/lib/net/ssh/proxy/errors.rb +2 -4
  53. data/lib/net/ssh/proxy/http.rb +18 -20
  54. data/lib/net/ssh/proxy/https.rb +8 -10
  55. data/lib/net/ssh/proxy/jump.rb +8 -10
  56. data/lib/net/ssh/proxy/socks4.rb +2 -4
  57. data/lib/net/ssh/proxy/socks5.rb +3 -6
  58. data/lib/net/ssh/service/forward.rb +9 -8
  59. data/lib/net/ssh/test/channel.rb +24 -26
  60. data/lib/net/ssh/test/extensions.rb +37 -35
  61. data/lib/net/ssh/test/kex.rb +6 -8
  62. data/lib/net/ssh/test/local_packet.rb +0 -2
  63. data/lib/net/ssh/test/packet.rb +3 -3
  64. data/lib/net/ssh/test/remote_packet.rb +6 -8
  65. data/lib/net/ssh/test/script.rb +25 -27
  66. data/lib/net/ssh/test/socket.rb +12 -15
  67. data/lib/net/ssh/test.rb +12 -12
  68. data/lib/net/ssh/transport/algorithms.rb +177 -118
  69. data/lib/net/ssh/transport/cipher_factory.rb +34 -50
  70. data/lib/net/ssh/transport/constants.rb +13 -9
  71. data/lib/net/ssh/transport/ctr.rb +8 -14
  72. data/lib/net/ssh/transport/hmac/abstract.rb +20 -5
  73. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  74. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  75. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  76. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  77. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  78. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  79. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  80. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  81. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  82. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  83. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  84. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  85. data/lib/net/ssh/transport/hmac.rb +13 -11
  86. data/lib/net/ssh/transport/identity_cipher.rb +11 -13
  87. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  88. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  89. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  90. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  91. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +5 -19
  92. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  93. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +30 -139
  94. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -8
  95. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  96. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +20 -81
  97. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +5 -4
  98. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +5 -4
  99. data/lib/net/ssh/transport/kex.rb +15 -10
  100. data/lib/net/ssh/transport/key_expander.rb +7 -8
  101. data/lib/net/ssh/transport/openssl.rb +149 -111
  102. data/lib/net/ssh/transport/packet_stream.rb +53 -22
  103. data/lib/net/ssh/transport/server_version.rb +17 -16
  104. data/lib/net/ssh/transport/session.rb +35 -11
  105. data/lib/net/ssh/transport/state.rb +44 -44
  106. data/lib/net/ssh/verifiers/accept_new.rb +7 -2
  107. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
  108. data/lib/net/ssh/verifiers/always.rb +10 -4
  109. data/lib/net/ssh/verifiers/never.rb +4 -2
  110. data/lib/net/ssh/version.rb +2 -2
  111. data/lib/net/ssh.rb +17 -9
  112. data/net-ssh-public_cert.pem +18 -19
  113. data/net-ssh.gemspec +9 -7
  114. data/support/ssh_tunnel_bug.rb +3 -3
  115. data.tar.gz.sig +0 -0
  116. metadata +65 -41
  117. metadata.gz.sig +0 -0
  118. data/.travis.yml +0 -52
  119. data/Gemfile.noed25519.lock +0 -41
  120. data/README.rdoc +0 -169
  121. data/lib/net/ssh/ruby_compat.rb +0 -13
  122. data/support/arcfour_check.rb +0 -20
@@ -6,14 +6,13 @@ module Net
6
6
  module SSH
7
7
  module Authentication
8
8
  module Methods
9
-
10
9
  # Implements the "publickey" SSH authentication method.
11
10
  class Publickey < Abstract
12
11
  # Attempts to perform public-key authentication for the given
13
12
  # username, trying each identity known to the key manager. If any of
14
13
  # them succeed, returns +true+, otherwise returns +false+. This
15
14
  # requires the presence of a key manager.
16
- def authenticate(next_service, username, password=nil)
15
+ def authenticate(next_service, username, password = nil)
17
16
  return false unless key_manager
18
17
 
19
18
  key_manager.each_identity do |identity|
@@ -27,41 +26,40 @@ module Net
27
26
 
28
27
  # Builds a packet that contains the request formatted for sending
29
28
  # a public-key request to the server.
30
- def build_request(pub_key, username, next_service, has_sig)
29
+ def build_request(pub_key, username, next_service, alg, has_sig)
31
30
  blob = Net::SSH::Buffer.new
32
31
  blob.write_key pub_key
33
32
 
34
33
  userauth_request(username, next_service, "publickey", has_sig,
35
- pub_key.ssh_type, blob.to_s)
34
+ alg, blob.to_s)
36
35
  end
37
36
 
38
37
  # Builds and sends a request formatted for a public-key
39
38
  # authentication request.
40
- def send_request(pub_key, username, next_service, signature=nil)
41
- msg = build_request(pub_key, username, next_service, !signature.nil?)
39
+ def send_request(pub_key, username, next_service, alg, signature = nil)
40
+ msg = build_request(pub_key, username, next_service, alg,
41
+ !signature.nil?)
42
42
  msg.write_string(signature) if signature
43
43
  send_message(msg)
44
44
  end
45
45
 
46
- # Attempts to perform public-key authentication for the given
47
- # username, with the given identity (public key). Returns +true+ if
48
- # successful, or +false+ otherwise.
49
- def authenticate_with(identity, next_service, username)
46
+ def authenticate_with_alg(identity, next_service, username, alg, sig_alg = nil)
50
47
  debug { "trying publickey (#{identity.fingerprint})" }
51
- send_request(identity, username, next_service)
48
+ send_request(identity, username, next_service, alg)
52
49
 
53
50
  message = session.next_message
54
51
 
55
52
  case message.type
56
53
  when USERAUTH_PK_OK
57
- buffer = build_request(identity, username, next_service, true)
54
+ buffer = build_request(identity, username, next_service, alg,
55
+ true)
58
56
  sig_data = Net::SSH::Buffer.new
59
57
  sig_data.write_string(session_id)
60
58
  sig_data.append(buffer.to_s)
61
59
 
62
- sig_blob = key_manager.sign(identity, sig_data)
60
+ sig_blob = key_manager.sign(identity, sig_data, sig_alg)
63
61
 
64
- send_request(identity, username, next_service, sig_blob.to_s)
62
+ send_request(identity, username, next_service, alg, sig_blob.to_s)
65
63
  message = session.next_message
66
64
 
67
65
  case message.type
@@ -77,18 +75,62 @@ module Net
77
75
  return false
78
76
  else
79
77
  raise Net::SSH::Exception,
80
- "unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
78
+ "unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
81
79
  end
82
80
 
83
81
  when USERAUTH_FAILURE
84
82
  return false
83
+ when USERAUTH_SUCCESS
84
+ return true
85
85
 
86
86
  else
87
87
  raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
88
88
  end
89
89
  end
90
- end
91
90
 
91
+ # Attempts to perform public-key authentication for the given
92
+ # username, with the given identity (public key). Returns +true+ if
93
+ # successful, or +false+ otherwise.
94
+ def authenticate_with(identity, next_service, username)
95
+ type = identity.ssh_type
96
+ if type == "ssh-rsa"
97
+ pubkey_algorithms.each do |pk_alg|
98
+ case pk_alg
99
+ when "rsa-sha2-512", "rsa-sha2-256", "ssh-rsa"
100
+ if authenticate_with_alg(identity, next_service, username, pk_alg, pk_alg)
101
+ # success
102
+ return true
103
+ end
104
+ end
105
+ end
106
+ elsif type == "ssh-rsa-cert-v01@openssh.com"
107
+ pubkey_algorithms.each do |pk_alg|
108
+ case pk_alg
109
+ when "rsa-sha2-512-cert-v01@openssh.com"
110
+ if authenticate_with_alg(identity, next_service, username, pk_alg, "rsa-sha2-512")
111
+ # success
112
+ return true
113
+ end
114
+ when "rsa-sha2-256-cert-v01@openssh.com"
115
+ if authenticate_with_alg(identity, next_service, username, pk_alg, "rsa-sha2-256")
116
+ # success
117
+ return true
118
+ end
119
+ when "ssh-rsa-cert-v01@openssh.com"
120
+ if authenticate_with_alg(identity, next_service, username, pk_alg)
121
+ # success
122
+ return true
123
+ end
124
+ end
125
+ end
126
+ elsif authenticate_with_alg(identity, next_service, username, type)
127
+ # success
128
+ return true
129
+ end
130
+ # failure
131
+ return false
132
+ end
133
+ end
92
134
  end
93
135
  end
94
136
  end
@@ -21,10 +21,9 @@ end
21
21
 
22
22
  require 'net/ssh/errors'
23
23
 
24
- module Net
25
- module SSH
24
+ module Net
25
+ module SSH
26
26
  module Authentication
27
-
28
27
  # This module encapsulates the implementation of a socket factory that
29
28
  # uses the PuTTY "pageant" utility to obtain information about SSH
30
29
  # identities.
@@ -33,36 +32,35 @@ module Net
33
32
  # by Guillaume Marçais (guillaume.marcais@free.fr). It is used and
34
33
  # relicensed by permission.
35
34
  module Pageant
36
-
37
35
  # From Putty pageant.c
38
36
  AGENT_MAX_MSGLEN = 8192
39
37
  AGENT_COPYDATA_ID = 0x804e50ba
40
-
38
+
41
39
  # The definition of the Windows methods and data structures used in
42
40
  # communicating with the pageant process.
43
41
  module Win # rubocop:disable Metrics/ModuleLength
44
42
  # Compatibility on initialization
45
43
  if RUBY_VERSION < "1.9"
46
44
  extend DL::Importable
47
-
45
+
48
46
  dlload 'user32.dll'
49
47
  dlload 'kernel32.dll'
50
48
  dlload 'advapi32.dll'
51
-
49
+
52
50
  SIZEOF_DWORD = DL.sizeof('L')
53
51
  elsif RUBY_VERSION < "2.1"
54
52
  extend DL::Importer
55
- dlload 'user32.dll','kernel32.dll', 'advapi32.dll'
53
+ dlload 'user32.dll', 'kernel32.dll', 'advapi32.dll'
56
54
  include DL::Win32Types
57
-
55
+
58
56
  SIZEOF_DWORD = DL::SIZEOF_LONG
59
57
  else
60
58
  extend Fiddle::Importer
61
- dlload 'user32.dll','kernel32.dll', 'advapi32.dll'
59
+ dlload 'user32.dll', 'kernel32.dll', 'advapi32.dll'
62
60
  include Fiddle::Win32Types
63
61
  SIZEOF_DWORD = Fiddle::SIZEOF_LONG
64
62
  end
65
-
63
+
66
64
  if RUBY_ENGINE == "jruby"
67
65
  typealias("HANDLE", "void *") # From winnt.h
68
66
  typealias("PHANDLE", "void *") # From winnt.h
@@ -76,105 +74,105 @@ module Net
76
74
  typealias("LPARAM", "long *") # From windef.h
77
75
  typealias("PDWORD_PTR", "long *") # From basetsd.h
78
76
  typealias("USHORT", "unsigned short") # From windef.h
79
-
77
+
80
78
  # From winbase.h, winnt.h
81
79
  INVALID_HANDLE_VALUE = -1
82
80
  NULL = nil
83
81
  PAGE_READWRITE = 0x0004
84
82
  FILE_MAP_WRITE = 2
85
83
  WM_COPYDATA = 74
86
-
84
+
87
85
  SMTO_NORMAL = 0 # From winuser.h
88
-
86
+
89
87
  SUFFIX = if RUBY_ENGINE == "jruby"
90
88
  "A"
91
89
  else
92
90
  ""
93
91
  end
94
-
92
+
95
93
  # args: lpClassName, lpWindowName
96
94
  extern "HWND FindWindow#{SUFFIX}(LPCTSTR, LPCTSTR)"
97
-
95
+
98
96
  # args: none
99
97
  extern 'DWORD GetCurrentThreadId()'
100
-
98
+
101
99
  # args: hFile, (ignored), flProtect, dwMaximumSizeHigh,
102
100
  # dwMaximumSizeLow, lpName
103
101
  extern "HANDLE CreateFileMapping#{SUFFIX}(HANDLE, void *, DWORD, " +
104
102
  "DWORD, DWORD, LPCTSTR)"
105
-
103
+
106
104
  # args: hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
107
105
  # dwfileOffsetLow, dwNumberOfBytesToMap
108
106
  extern 'LPVOID MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, DWORD)'
109
-
107
+
110
108
  # args: lpBaseAddress
111
109
  extern 'BOOL UnmapViewOfFile(LPCVOID)'
112
-
110
+
113
111
  # args: hObject
114
112
  extern 'BOOL CloseHandle(HANDLE)'
115
-
113
+
116
114
  # args: hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult
117
115
  extern "LRESULT SendMessageTimeout#{SUFFIX}(HWND, UINT, WPARAM, LPARAM, " +
118
116
  "UINT, UINT, PDWORD_PTR)"
119
-
117
+
120
118
  # args: none
121
119
  extern 'DWORD GetLastError()'
122
-
120
+
123
121
  # args: none
124
122
  extern 'HANDLE GetCurrentProcess()'
125
-
123
+
126
124
  # args: hProcessHandle, dwDesiredAccess, (out) phNewTokenHandle
127
125
  extern 'BOOL OpenProcessToken(HANDLE, DWORD, PHANDLE)'
128
-
126
+
129
127
  # args: hTokenHandle, uTokenInformationClass,
130
128
  # (out) lpTokenInformation, dwTokenInformationLength
131
129
  # (out) pdwInfoReturnLength
132
130
  extern 'BOOL GetTokenInformation(HANDLE, UINT, LPVOID, DWORD, ' +
133
131
  'PDWORD)'
134
-
132
+
135
133
  # args: (out) lpSecurityDescriptor, dwRevisionLevel
136
134
  extern 'BOOL InitializeSecurityDescriptor(LPVOID, DWORD)'
137
-
135
+
138
136
  # args: (out) lpSecurityDescriptor, lpOwnerSid, bOwnerDefaulted
139
137
  extern 'BOOL SetSecurityDescriptorOwner(LPVOID, LPVOID, BOOL)'
140
-
138
+
141
139
  # args: pSecurityDescriptor
142
140
  extern 'BOOL IsValidSecurityDescriptor(LPVOID)'
143
-
141
+
144
142
  # Constants needed for security attribute retrieval.
145
143
  # Specifies the access mask corresponding to the desired access
146
144
  # rights.
147
145
  TOKEN_QUERY = 0x8
148
-
146
+
149
147
  # The value of TOKEN_USER from the TOKEN_INFORMATION_CLASS enum.
150
148
  TOKEN_USER_INFORMATION_CLASS = 1
151
-
149
+
152
150
  # The initial revision level assigned to the security descriptor.
153
151
  REVISION = 1
154
-
152
+
155
153
  # Structs for security attribute functions.
156
154
  # Holds the retrieved user access token.
157
155
  TOKEN_USER = struct ['void * SID', 'DWORD ATTRIBUTES']
158
-
156
+
159
157
  # Contains the security descriptor, this gets passed to the
160
158
  # function that constructs the shared memory map.
161
159
  SECURITY_ATTRIBUTES = struct ['DWORD nLength',
162
160
  'LPVOID lpSecurityDescriptor',
163
161
  'BOOL bInheritHandle']
164
-
162
+
165
163
  # The security descriptor holds security information.
166
164
  SECURITY_DESCRIPTOR = struct ['UCHAR Revision', 'UCHAR Sbz1',
167
165
  'USHORT Control', 'LPVOID Owner',
168
166
  'LPVOID Group', 'LPVOID Sacl',
169
167
  'LPVOID Dacl']
170
-
168
+
171
169
  # The COPYDATASTRUCT is used to send WM_COPYDATA messages
172
170
  COPYDATASTRUCT = if RUBY_ENGINE == "jruby"
173
171
  struct ['ULONG_PTR dwData', 'DWORD cbData', 'LPVOID lpData']
174
172
  else
175
173
  struct ['uintptr_t dwData', 'DWORD cbData', 'LPVOID lpData']
176
174
  end
177
-
175
+
178
176
  # Compatibility for security attribute retrieval.
179
177
  if RUBY_VERSION < "1.9"
180
178
  # Alias functions to > 1.9 capitalization
@@ -196,15 +194,15 @@ module Net
196
194
  alias_method new_name, name
197
195
  module_function new_name
198
196
  end
199
-
197
+
200
198
  def self.malloc_ptr(size)
201
199
  return DL.malloc(size)
202
200
  end
203
-
201
+
204
202
  def self.get_ptr(data)
205
203
  return data.to_ptr
206
204
  end
207
-
205
+
208
206
  def self.set_ptr_data(ptr, data)
209
207
  ptr[0] = data
210
208
  end
@@ -220,15 +218,15 @@ module Net
220
218
  attach_function :malloc, [:size_t], :pointer
221
219
  attach_function :free, [:pointer], :void
222
220
  end
223
-
221
+
224
222
  def self.malloc_ptr(size)
225
223
  Fiddle::Pointer.new(LibC.malloc(size), size, LibC.method(:free))
226
224
  end
227
-
225
+
228
226
  def self.get_ptr(ptr)
229
227
  return data.address
230
228
  end
231
-
229
+
232
230
  def self.set_ptr_data(ptr, data)
233
231
  ptr.write_string_length(data, data.size)
234
232
  end
@@ -236,19 +234,19 @@ module Net
236
234
  def self.malloc_ptr(size)
237
235
  return DL::CPtr.malloc(size, DL::RUBY_FREE)
238
236
  end
239
-
237
+
240
238
  def self.get_ptr(data)
241
239
  return DL::CPtr.to_ptr data
242
240
  end
243
-
241
+
244
242
  def self.set_ptr_data(ptr, data)
245
- DL::CPtr.new(ptr)[0,data.size] = data
243
+ DL::CPtr.new(ptr)[0, data.size] = data
246
244
  end
247
245
  end
248
-
246
+
249
247
  def self.get_security_attributes_for_user
250
248
  user = get_current_user
251
-
249
+
252
250
  psd_information = malloc_ptr(Win::SECURITY_DESCRIPTOR.size)
253
251
  raise_error_if_zero(
254
252
  Win.InitializeSecurityDescriptor(psd_information,
@@ -261,45 +259,46 @@ module Net
261
259
  raise_error_if_zero(
262
260
  Win.IsValidSecurityDescriptor(psd_information)
263
261
  )
264
-
262
+
265
263
  sa = Win::SECURITY_ATTRIBUTES.new(to_struct_ptr(malloc_ptr(Win::SECURITY_ATTRIBUTES.size)))
266
264
  sa.nLength = Win::SECURITY_ATTRIBUTES.size
267
265
  sa.lpSecurityDescriptor = psd_information.to_i
268
266
  sa.bInheritHandle = 1
269
-
267
+
270
268
  return sa
271
269
  end
272
-
270
+
273
271
  if RUBY_ENGINE == "jruby"
274
272
  def self.ptr_to_s(ptr, size)
275
273
  ret = ptr.to_s(size)
276
274
  ret << "\x00" while ret.size < size
277
275
  ret
278
276
  end
279
-
277
+
280
278
  def self.ptr_to_handle(phandle)
281
279
  phandle.ptr
282
280
  end
283
-
281
+
284
282
  def self.ptr_to_dword(ptr)
285
283
  first = ptr.ptr.to_i
286
- second = ptr_to_s(ptr,Win::SIZEOF_DWORD).unpack('L')[0]
284
+ second = ptr_to_s(ptr, Win::SIZEOF_DWORD).unpack('L')[0]
287
285
  raise "Error" unless first == second
286
+
288
287
  first
289
288
  end
290
-
289
+
291
290
  def self.to_token_user(ptoken_information)
292
291
  TOKEN_USER.new(ptoken_information.to_ptr)
293
292
  end
294
-
293
+
295
294
  def self.to_struct_ptr(ptr)
296
295
  ptr.to_ptr
297
296
  end
298
-
297
+
299
298
  def self.get_sid(user)
300
- ptr_to_s(user.to_ptr.ptr,Win::SIZEOF_DWORD).unpack('L')[0]
299
+ ptr_to_s(user.to_ptr.ptr, Win::SIZEOF_DWORD).unpack('L')[0]
301
300
  end
302
-
301
+
303
302
  def self.get_sid_ptr(user)
304
303
  user.to_ptr.ptr
305
304
  end
@@ -307,39 +306,39 @@ module Net
307
306
  def self.get_sid(user)
308
307
  user.SID
309
308
  end
310
-
309
+
311
310
  def self.ptr_to_handle(phandle)
312
311
  phandle.ptr.to_i
313
312
  end
314
-
313
+
315
314
  def self.to_struct_ptr(ptr)
316
315
  ptr
317
316
  end
318
-
317
+
319
318
  def self.ptr_to_dword(ptr)
320
319
  ptr.to_s(Win::SIZEOF_DWORD).unpack('L')[0]
321
320
  end
322
-
321
+
323
322
  def self.to_token_user(ptoken_information)
324
323
  TOKEN_USER.new(ptoken_information)
325
324
  end
326
-
325
+
327
326
  def self.get_sid_ptr(user)
328
327
  user.SID
329
328
  end
330
329
  end
331
-
330
+
332
331
  def self.get_current_user
333
332
  token_handle = open_process_token(Win.GetCurrentProcess,
334
333
  Win::TOKEN_QUERY)
335
334
  token_user = get_token_information(token_handle,
336
- Win::TOKEN_USER_INFORMATION_CLASS)
335
+ Win::TOKEN_USER_INFORMATION_CLASS)
337
336
  return token_user
338
337
  end
339
-
338
+
340
339
  def self.open_process_token(process_handle, desired_access)
341
340
  ptoken_handle = malloc_ptr(Win::SIZEOF_DWORD)
342
-
341
+
343
342
  raise_error_if_zero(
344
343
  Win.OpenProcessToken(process_handle, desired_access,
345
344
  ptoken_handle)
@@ -347,12 +346,12 @@ module Net
347
346
  token_handle = ptr_to_handle(ptoken_handle)
348
347
  return token_handle
349
348
  end
350
-
349
+
351
350
  def self.get_token_information(token_handle,
352
351
  token_information_class)
353
352
  # Hold the size of the information to be returned
354
353
  preturn_length = malloc_ptr(Win::SIZEOF_DWORD)
355
-
354
+
356
355
  # Going to throw an INSUFFICIENT_BUFFER_ERROR, but that is ok
357
356
  # here. This is retrieving the size of the information to be
358
357
  # returned.
@@ -360,7 +359,7 @@ module Net
360
359
  token_information_class,
361
360
  Win::NULL, 0, preturn_length)
362
361
  ptoken_information = malloc_ptr(ptr_to_dword(preturn_length))
363
-
362
+
364
363
  # This call is going to write the requested information to
365
364
  # the memory location referenced by token_information.
366
365
  raise_error_if_zero(
@@ -370,74 +369,76 @@ module Net
370
369
  ptoken_information.size,
371
370
  preturn_length)
372
371
  )
373
-
372
+
374
373
  return to_token_user(ptoken_information)
375
374
  end
376
-
375
+
377
376
  def self.raise_error_if_zero(result)
378
377
  if result == 0
379
378
  raise "Windows error: #{Win.GetLastError}"
380
379
  end
381
380
  end
382
-
381
+
383
382
  # Get a null-terminated string given a string.
384
383
  def self.get_cstr(str)
385
384
  return str + "\000"
386
385
  end
387
386
  end
388
-
387
+
389
388
  # This is the pseudo-socket implementation that mimics the interface of
390
389
  # a socket, translating each request into a Windows messaging call to
391
390
  # the pageant daemon. This allows pageant support to be implemented
392
391
  # simply by replacing the socket factory used by the Agent class.
393
392
  class Socket
394
393
  private_class_method :new
395
-
394
+
396
395
  # The factory method for creating a new Socket instance.
397
396
  def self.open
398
397
  new
399
398
  end
400
-
399
+
401
400
  # Create a new instance that communicates with the running pageant
402
401
  # instance. If no such instance is running, this will cause an error.
403
402
  def initialize
404
403
  @win = Win.FindWindow("Pageant", "Pageant")
405
-
404
+
406
405
  if @win.to_i == 0
407
406
  raise Net::SSH::Exception,
408
- "pageant process not running"
407
+ "pageant process not running"
409
408
  end
410
-
409
+
411
410
  @input_buffer = Net::SSH::Buffer.new
412
411
  @output_buffer = Net::SSH::Buffer.new
413
412
  end
414
-
413
+
415
414
  # Forwards the data to #send_query, ignoring any arguments after
416
415
  # the first.
417
416
  def send(data, *args)
418
417
  @input_buffer.append(data)
419
-
418
+
420
419
  ret = data.length
421
-
420
+
422
421
  while true
423
422
  return ret if @input_buffer.length < 4
423
+
424
424
  msg_length = @input_buffer.read_long + 4
425
425
  @input_buffer.reset!
426
-
426
+
427
427
  return ret if @input_buffer.length < msg_length
428
+
428
429
  msg = @input_buffer.read!(msg_length)
429
430
  @output_buffer.append(send_query(msg))
430
431
  end
431
432
  end
432
-
433
+
433
434
  # Reads +n+ bytes from the cached result of the last query. If +n+
434
435
  # is +nil+, returns all remaining data from the last query.
435
436
  def read(n = nil)
436
437
  @output_buffer.read(n)
437
438
  end
438
-
439
+
439
440
  def close; end
440
-
441
+
441
442
  # Packages the given query string and sends it to the pageant
442
443
  # process via the Windows messaging subsystem. The result is
443
444
  # cached, to be returned piece-wise when #read is called.
@@ -446,29 +447,29 @@ module Net
446
447
  filemap = 0
447
448
  ptr = nil
448
449
  id = Win.malloc_ptr(Win::SIZEOF_DWORD)
449
-
450
+
450
451
  mapname = "PageantRequest%08x" % Win.GetCurrentThreadId()
451
452
  security_attributes = Win.get_ptr Win.get_security_attributes_for_user
452
-
453
+
453
454
  filemap = Win.CreateFileMapping(Win::INVALID_HANDLE_VALUE,
454
455
  security_attributes,
455
456
  Win::PAGE_READWRITE, 0,
456
457
  AGENT_MAX_MSGLEN, mapname)
457
-
458
+
458
459
  if filemap == 0 || filemap == Win::INVALID_HANDLE_VALUE
459
460
  raise Net::SSH::Exception,
460
- "Creation of file mapping failed with error: #{Win.GetLastError}"
461
+ "Creation of file mapping failed with error: #{Win.GetLastError}"
461
462
  end
462
-
463
+
463
464
  ptr = Win.MapViewOfFile(filemap, Win::FILE_MAP_WRITE, 0, 0,
464
465
  0)
465
-
466
+
466
467
  if ptr.nil? || ptr.null?
467
468
  raise Net::SSH::Exception, "Mapping of file failed"
468
469
  end
469
-
470
+
470
471
  Win.set_ptr_data(ptr, query)
471
-
472
+
472
473
  # using struct to achieve proper alignment and field size on 64-bit platform
473
474
  cds = Win::COPYDATASTRUCT.new(Win.malloc_ptr(Win::COPYDATASTRUCT.size))
474
475
  cds.dwData = AGENT_COPYDATA_ID
@@ -476,14 +477,14 @@ module Net
476
477
  cds.lpData = Win.get_cstr(mapname)
477
478
  succ = Win.SendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL,
478
479
  cds.to_ptr, Win::SMTO_NORMAL, 5000, id)
479
-
480
+
480
481
  if succ > 0
481
482
  retlen = 4 + ptr.to_s(4).unpack("N")[0]
482
483
  res = ptr.to_s(retlen)
483
484
  else
484
485
  raise Net::SSH::Exception, "Message failed with error: #{Win.GetLastError}"
485
486
  end
486
-
487
+
487
488
  return res
488
489
  ensure
489
490
  Win.UnmapViewOfFile(ptr) unless ptr.nil? || ptr.null?
@@ -491,7 +492,6 @@ module Net
491
492
  end
492
493
  end
493
494
  end
494
-
495
495
  end
496
496
  end
497
497
  end
@@ -1,4 +1,3 @@
1
-
2
1
  require 'openssl'
3
2
 
4
3
  module Net
@@ -23,12 +22,12 @@ module Net
23
22
  # returned by OpenSSH's <tt>`ssh-add -l -E SHA256`</tt>, i.e.,
24
23
  # trailing base64 padding '=' characters are stripped and the
25
24
  # literal string +SHA256:+ is prepended.
26
- def fingerprint(algorithm='MD5')
25
+ def fingerprint(algorithm = 'MD5')
27
26
  @fingerprint ||= {}
28
27
  @fingerprint[algorithm] ||= PubKeyFingerprint.fingerprint(to_blob, algorithm)
29
28
  end
30
29
 
31
- def self.fingerprint(blob, algorithm='MD5')
30
+ def self.fingerprint(blob, algorithm = 'MD5')
32
31
  case algorithm.to_s.upcase
33
32
  when 'MD5'
34
33
  OpenSSL::Digest.hexdigest(algorithm, blob).scan(/../).join(":")