net-ssh 2.9.0 → 2.9.1
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.
- data.tar.gz.sig +0 -0
- data/.travis.yml +0 -1
- data/CHANGES.txt +6 -0
- data/lib/net/ssh/authentication/pageant.rb +197 -68
- data/lib/net/ssh/buffer.rb +1 -1
- data/lib/net/ssh/config.rb +12 -2
- data/lib/net/ssh/transport/cipher_factory.rb +3 -0
- data/lib/net/ssh/version.rb +1 -1
- data/net-ssh.gemspec +4 -2
- data/test/configs/negative_match +6 -0
- data/test/manual/test_pageant.rb +37 -0
- data/test/test_config.rb +6 -0
- metadata +4 -2
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
|
Binary file
|
data/.travis.yml
CHANGED
data/CHANGES.txt
CHANGED
|
@@ -27,15 +27,21 @@ module Net; module SSH; module Authentication
|
|
|
27
27
|
# The definition of the Windows methods and data structures used in
|
|
28
28
|
# communicating with the pageant process.
|
|
29
29
|
module Win
|
|
30
|
+
# Compatibility on initialization
|
|
30
31
|
if RUBY_VERSION < "1.9"
|
|
31
32
|
extend DL::Importable
|
|
32
33
|
|
|
33
34
|
dlload 'user32'
|
|
34
35
|
dlload 'kernel32'
|
|
36
|
+
dlload 'advapi32'
|
|
37
|
+
|
|
38
|
+
SIZEOF_DWORD = DL.sizeof('L')
|
|
35
39
|
else
|
|
36
40
|
extend DL::Importer
|
|
37
|
-
dlload 'user32','kernel32'
|
|
41
|
+
dlload 'user32','kernel32', 'advapi32'
|
|
38
42
|
include DL::Win32Types
|
|
43
|
+
|
|
44
|
+
SIZEOF_DWORD = DL::SIZEOF_LONG
|
|
39
45
|
end
|
|
40
46
|
|
|
41
47
|
typealias("LPCTSTR", "char *") # From winnt.h
|
|
@@ -45,6 +51,7 @@ module Net; module SSH; module Authentication
|
|
|
45
51
|
typealias("WPARAM", "unsigned int *") # From windef.h
|
|
46
52
|
typealias("LPARAM", "long *") # From windef.h
|
|
47
53
|
typealias("PDWORD_PTR", "long *") # From basetsd.h
|
|
54
|
+
typealias("USHORT", "unsigned short") # From windef.h
|
|
48
55
|
|
|
49
56
|
# From winbase.h, winnt.h
|
|
50
57
|
INVALID_HANDLE_VALUE = -1
|
|
@@ -63,8 +70,8 @@ module Net; module SSH; module Authentication
|
|
|
63
70
|
|
|
64
71
|
# args: hFile, (ignored), flProtect, dwMaximumSizeHigh,
|
|
65
72
|
# dwMaximumSizeLow, lpName
|
|
66
|
-
extern 'HANDLE CreateFileMapping(HANDLE, void *, DWORD,
|
|
67
|
-
'DWORD, LPCTSTR)'
|
|
73
|
+
extern 'HANDLE CreateFileMapping(HANDLE, void *, DWORD, ' +
|
|
74
|
+
'DWORD, DWORD, LPCTSTR)'
|
|
68
75
|
|
|
69
76
|
# args: hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
|
|
70
77
|
# dwfileOffsetLow, dwNumberOfBytesToMap
|
|
@@ -79,9 +86,180 @@ module Net; module SSH; module Authentication
|
|
|
79
86
|
# args: hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult
|
|
80
87
|
extern 'LRESULT SendMessageTimeout(HWND, UINT, WPARAM, LPARAM, ' +
|
|
81
88
|
'UINT, UINT, PDWORD_PTR)'
|
|
89
|
+
|
|
90
|
+
# args: none
|
|
91
|
+
extern 'DWORD GetLastError()'
|
|
92
|
+
|
|
93
|
+
# args: none
|
|
94
|
+
extern 'HANDLE GetCurrentProcess()'
|
|
95
|
+
|
|
96
|
+
# args: hProcessHandle, dwDesiredAccess, (out) phNewTokenHandle
|
|
97
|
+
extern 'BOOL OpenProcessToken(HANDLE, DWORD, PHANDLE)'
|
|
98
|
+
|
|
99
|
+
# args: hTokenHandle, uTokenInformationClass,
|
|
100
|
+
# (out) lpTokenInformation, dwTokenInformationLength
|
|
101
|
+
# (out) pdwInfoReturnLength
|
|
102
|
+
extern 'BOOL GetTokenInformation(HANDLE, UINT, LPVOID, DWORD, ' +
|
|
103
|
+
'PDWORD)'
|
|
104
|
+
|
|
105
|
+
# args: (out) lpSecurityDescriptor, dwRevisionLevel
|
|
106
|
+
extern 'BOOL InitializeSecurityDescriptor(LPVOID, DWORD)'
|
|
107
|
+
|
|
108
|
+
# args: (out) lpSecurityDescriptor, lpOwnerSid, bOwnerDefaulted
|
|
109
|
+
extern 'BOOL SetSecurityDescriptorOwner(LPVOID, LPVOID, BOOL)'
|
|
110
|
+
|
|
111
|
+
# args: pSecurityDescriptor
|
|
112
|
+
extern 'BOOL IsValidSecurityDescriptor(LPVOID)'
|
|
113
|
+
|
|
114
|
+
# Constants needed for security attribute retrieval.
|
|
115
|
+
# Specifies the access mask corresponding to the desired access
|
|
116
|
+
# rights.
|
|
117
|
+
TOKEN_QUERY = 0x8
|
|
118
|
+
|
|
119
|
+
# The value of TOKEN_USER from the TOKEN_INFORMATION_CLASS enum.
|
|
120
|
+
TOKEN_USER_INFORMATION_CLASS = 1
|
|
121
|
+
|
|
122
|
+
# The initial revision level assigned to the security descriptor.
|
|
123
|
+
REVISION = 1
|
|
124
|
+
|
|
125
|
+
# Structs for security attribute functions.
|
|
126
|
+
# Holds the retrieved user access token.
|
|
127
|
+
TOKEN_USER = struct ['void * SID', 'DWORD ATTRIBUTES']
|
|
128
|
+
|
|
129
|
+
# Contains the security descriptor, this gets passed to the
|
|
130
|
+
# function that constructs the shared memory map.
|
|
131
|
+
SECURITY_ATTRIBUTES = struct ['DWORD nLength',
|
|
132
|
+
'LPVOID lpSecurityDescriptor',
|
|
133
|
+
'BOOL bInheritHandle']
|
|
134
|
+
|
|
135
|
+
# The security descriptor holds security information.
|
|
136
|
+
SECURITY_DESCRIPTOR = struct ['UCHAR Revision', 'UCHAR Sbz1',
|
|
137
|
+
'USHORT Control', 'LPVOID Owner',
|
|
138
|
+
'LPVOID Group', 'LPVOID Sacl',
|
|
139
|
+
'LPVOID Dacl']
|
|
140
|
+
|
|
141
|
+
# Compatibility for security attribute retrieval.
|
|
82
142
|
if RUBY_VERSION < "1.9"
|
|
83
|
-
|
|
84
|
-
|
|
143
|
+
# Alias functions to > 1.9 capitalization
|
|
144
|
+
%w(findWindow
|
|
145
|
+
getCurrentProcess
|
|
146
|
+
initializeSecurityDescriptor
|
|
147
|
+
setSecurityDescriptorOwner
|
|
148
|
+
isValidSecurityDescriptor
|
|
149
|
+
openProcessToken
|
|
150
|
+
getTokenInformation
|
|
151
|
+
getLastError
|
|
152
|
+
getCurrentThreadId
|
|
153
|
+
createFileMapping
|
|
154
|
+
mapViewOfFile
|
|
155
|
+
sendMessageTimeout
|
|
156
|
+
unmapViewOfFile
|
|
157
|
+
closeHandle).each do |name|
|
|
158
|
+
new_name = name[0].chr.upcase + name[1..name.length]
|
|
159
|
+
alias_method new_name, name
|
|
160
|
+
module_function new_name
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def self.malloc_ptr(size)
|
|
164
|
+
return DL.malloc(size)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def self.get_ptr(data)
|
|
168
|
+
return data.to_ptr
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def self.set_ptr_data(ptr, data)
|
|
172
|
+
ptr[0] = data
|
|
173
|
+
end
|
|
174
|
+
else
|
|
175
|
+
def self.malloc_ptr(size)
|
|
176
|
+
return DL::CPtr.malloc(size, DL::RUBY_FREE)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def self.get_ptr(data)
|
|
180
|
+
return DL::CPtr.to_ptr data
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def self.set_ptr_data(ptr, data)
|
|
184
|
+
DL::CPtr.new(ptr)[0,data.size] = data
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def self.get_security_attributes_for_user
|
|
189
|
+
user = get_current_user
|
|
190
|
+
|
|
191
|
+
psd_information = malloc_ptr(Win::SECURITY_DESCRIPTOR.size)
|
|
192
|
+
raise_error_if_zero(
|
|
193
|
+
Win.InitializeSecurityDescriptor(psd_information,
|
|
194
|
+
Win::REVISION))
|
|
195
|
+
raise_error_if_zero(
|
|
196
|
+
Win.SetSecurityDescriptorOwner(psd_information, user.SID,
|
|
197
|
+
0))
|
|
198
|
+
raise_error_if_zero(
|
|
199
|
+
Win.IsValidSecurityDescriptor(psd_information))
|
|
200
|
+
|
|
201
|
+
nLength = Win::SECURITY_ATTRIBUTES.size
|
|
202
|
+
lpSecurityDescriptor = psd_information
|
|
203
|
+
bInheritHandle = 1
|
|
204
|
+
sa = [nLength, lpSecurityDescriptor.to_i,
|
|
205
|
+
bInheritHandle].pack("LLC")
|
|
206
|
+
|
|
207
|
+
return sa
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def self.get_current_user
|
|
211
|
+
token_handle = open_process_token(Win.GetCurrentProcess,
|
|
212
|
+
Win::TOKEN_QUERY)
|
|
213
|
+
token_user = get_token_information(token_handle,
|
|
214
|
+
Win::TOKEN_USER_INFORMATION_CLASS)
|
|
215
|
+
return token_user
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def self.open_process_token(process_handle, desired_access)
|
|
219
|
+
ptoken_handle = malloc_ptr(Win::SIZEOF_DWORD)
|
|
220
|
+
|
|
221
|
+
raise_error_if_zero(
|
|
222
|
+
Win.OpenProcessToken(process_handle, desired_access,
|
|
223
|
+
ptoken_handle))
|
|
224
|
+
token_handle = ptoken_handle.ptr.to_i
|
|
225
|
+
|
|
226
|
+
return token_handle
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def self.get_token_information(token_handle,
|
|
230
|
+
token_information_class)
|
|
231
|
+
# Hold the size of the information to be returned
|
|
232
|
+
preturn_length = malloc_ptr(Win::SIZEOF_DWORD)
|
|
233
|
+
|
|
234
|
+
# Going to throw an INSUFFICIENT_BUFFER_ERROR, but that is ok
|
|
235
|
+
# here. This is retrieving the size of the information to be
|
|
236
|
+
# returned.
|
|
237
|
+
Win.GetTokenInformation(token_handle,
|
|
238
|
+
token_information_class,
|
|
239
|
+
Win::NULL, 0, preturn_length)
|
|
240
|
+
ptoken_information = malloc_ptr(preturn_length.ptr.to_i)
|
|
241
|
+
|
|
242
|
+
# This call is going to write the requested information to
|
|
243
|
+
# the memory location referenced by token_information.
|
|
244
|
+
raise_error_if_zero(
|
|
245
|
+
Win.GetTokenInformation(token_handle,
|
|
246
|
+
token_information_class,
|
|
247
|
+
ptoken_information,
|
|
248
|
+
ptoken_information.size,
|
|
249
|
+
preturn_length))
|
|
250
|
+
|
|
251
|
+
return TOKEN_USER.new(ptoken_information)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def self.raise_error_if_zero(result)
|
|
255
|
+
if result == 0
|
|
256
|
+
raise "Windows error: #{Win.GetLastError}"
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Get a null-terminated string given a string.
|
|
261
|
+
def self.get_cstr(str)
|
|
262
|
+
return str + "\000"
|
|
85
263
|
end
|
|
86
264
|
end
|
|
87
265
|
|
|
@@ -140,78 +318,27 @@ module Net; module SSH; module Authentication
|
|
|
140
318
|
|
|
141
319
|
def close
|
|
142
320
|
end
|
|
143
|
-
|
|
144
|
-
def send_query(query)
|
|
145
|
-
if RUBY_VERSION < "1.9"
|
|
146
|
-
send_query_18(query)
|
|
147
|
-
else
|
|
148
|
-
send_query_19(query)
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
# Packages the given query string and sends it to the pageant
|
|
153
|
-
# process via the Windows messaging subsystem. The result is
|
|
154
|
-
# cached, to be returned piece-wise when #read is called.
|
|
155
|
-
def send_query_18(query)
|
|
156
|
-
res = nil
|
|
157
|
-
filemap = 0
|
|
158
|
-
ptr = nil
|
|
159
|
-
id = DL::PtrData.malloc(DL.sizeof("L"))
|
|
160
|
-
|
|
161
|
-
mapname = "PageantRequest%08x\000" % Win.getCurrentThreadId()
|
|
162
|
-
filemap = Win.createFileMapping(Win::INVALID_HANDLE_VALUE,
|
|
163
|
-
Win::NULL,
|
|
164
|
-
Win::PAGE_READWRITE, 0,
|
|
165
|
-
AGENT_MAX_MSGLEN, mapname)
|
|
166
|
-
if filemap == 0
|
|
167
|
-
raise Net::SSH::Exception,
|
|
168
|
-
"Creation of file mapping failed"
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
ptr = Win.mapViewOfFile(filemap, Win::FILE_MAP_WRITE, 0, 0,
|
|
172
|
-
AGENT_MAX_MSGLEN)
|
|
173
|
-
|
|
174
|
-
if ptr.nil? || ptr.null?
|
|
175
|
-
raise Net::SSH::Exception, "Mapping of file failed"
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
ptr[0] = query
|
|
179
|
-
|
|
180
|
-
cds = [AGENT_COPYDATA_ID, mapname.size + 1, mapname].
|
|
181
|
-
pack("LLp").to_ptr
|
|
182
|
-
succ = Win.sendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL,
|
|
183
|
-
cds, Win::SMTO_NORMAL, 5000, id)
|
|
184
|
-
|
|
185
|
-
if succ > 0
|
|
186
|
-
retlen = 4 + ptr.to_s(4).unpack("N")[0]
|
|
187
|
-
res = ptr.to_s(retlen)
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
return res
|
|
191
|
-
ensure
|
|
192
|
-
Win.unmapViewOfFile(ptr) unless ptr.nil? || ptr.null?
|
|
193
|
-
Win.closeHandle(filemap) if filemap != 0
|
|
194
|
-
end
|
|
195
321
|
|
|
196
322
|
# Packages the given query string and sends it to the pageant
|
|
197
323
|
# process via the Windows messaging subsystem. The result is
|
|
198
324
|
# cached, to be returned piece-wise when #read is called.
|
|
199
|
-
def
|
|
325
|
+
def send_query(query)
|
|
200
326
|
res = nil
|
|
201
327
|
filemap = 0
|
|
202
328
|
ptr = nil
|
|
203
|
-
id =
|
|
329
|
+
id = Win.malloc_ptr(Win::SIZEOF_DWORD)
|
|
204
330
|
|
|
205
|
-
mapname = "PageantRequest%08x
|
|
331
|
+
mapname = "PageantRequest%08x" % Win.GetCurrentThreadId()
|
|
332
|
+
security_attributes = Win.get_ptr Win.get_security_attributes_for_user
|
|
206
333
|
|
|
207
|
-
filemap = Win.CreateFileMapping(Win::INVALID_HANDLE_VALUE,
|
|
208
|
-
|
|
209
|
-
Win::PAGE_READWRITE, 0,
|
|
334
|
+
filemap = Win.CreateFileMapping(Win::INVALID_HANDLE_VALUE,
|
|
335
|
+
security_attributes,
|
|
336
|
+
Win::PAGE_READWRITE, 0,
|
|
210
337
|
AGENT_MAX_MSGLEN, mapname)
|
|
211
338
|
|
|
212
339
|
if filemap == 0 || filemap == Win::INVALID_HANDLE_VALUE
|
|
213
340
|
raise Net::SSH::Exception,
|
|
214
|
-
"Creation of file mapping failed"
|
|
341
|
+
"Creation of file mapping failed with error: #{Win.GetLastError}"
|
|
215
342
|
end
|
|
216
343
|
|
|
217
344
|
ptr = Win.MapViewOfFile(filemap, Win::FILE_MAP_WRITE, 0, 0,
|
|
@@ -221,17 +348,19 @@ module Net; module SSH; module Authentication
|
|
|
221
348
|
raise Net::SSH::Exception, "Mapping of file failed"
|
|
222
349
|
end
|
|
223
350
|
|
|
224
|
-
|
|
351
|
+
Win.set_ptr_data(ptr, query)
|
|
225
352
|
|
|
226
|
-
cds =
|
|
227
|
-
|
|
353
|
+
cds = Win.get_ptr [AGENT_COPYDATA_ID, mapname.size + 1,
|
|
354
|
+
Win.get_cstr(mapname)].pack("LLp")
|
|
228
355
|
succ = Win.SendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL,
|
|
229
356
|
cds, Win::SMTO_NORMAL, 5000, id)
|
|
230
357
|
|
|
231
358
|
if succ > 0
|
|
232
359
|
retlen = 4 + ptr.to_s(4).unpack("N")[0]
|
|
233
360
|
res = ptr.to_s(retlen)
|
|
234
|
-
|
|
361
|
+
else
|
|
362
|
+
raise Net::SSH::Exception, "Message failed with error: #{Win.GetLastError}"
|
|
363
|
+
end
|
|
235
364
|
|
|
236
365
|
return res
|
|
237
366
|
ensure
|
data/lib/net/ssh/buffer.rb
CHANGED
|
@@ -255,7 +255,7 @@ module Net; module SSH
|
|
|
255
255
|
key.e = read_bignum
|
|
256
256
|
key.n = read_bignum
|
|
257
257
|
|
|
258
|
-
when /^ecdsa\-sha2\-(\w*)
|
|
258
|
+
when /^ecdsa\-sha2\-(\w*)$/, /^ssh-ed25519(-cert-v01@openssh.com)?$/
|
|
259
259
|
unless defined?(OpenSSL::PKey::EC)
|
|
260
260
|
raise NotImplementedError, "unsupported key type `#{type}'"
|
|
261
261
|
else
|
data/lib/net/ssh/config.rb
CHANGED
|
@@ -103,8 +103,18 @@ module Net; module SSH
|
|
|
103
103
|
if key == 'host'
|
|
104
104
|
# Support "Host host1 host2 hostN".
|
|
105
105
|
# See http://github.com/net-ssh/net-ssh/issues#issue/6
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
negative_hosts, positive_hosts = value.to_s.split(/\s+/).partition { |h| h.start_with?('!') }
|
|
107
|
+
|
|
108
|
+
# Check for negative patterns first. If the host matches, that overrules any other positive match.
|
|
109
|
+
# The host substring code is used to strip out the starting "!" so the regexp will be correct.
|
|
110
|
+
negative_match = negative_hosts.select { |h| host =~ pattern2regex(h[1..-1]) }.first
|
|
111
|
+
|
|
112
|
+
if negative_match
|
|
113
|
+
matched_host = nil
|
|
114
|
+
else
|
|
115
|
+
matched_host = positive_hosts.select { |h| host =~ pattern2regex(h) }.first
|
|
116
|
+
end
|
|
117
|
+
|
|
108
118
|
seen_host = true
|
|
109
119
|
settings[key] = host
|
|
110
120
|
elsif !seen_host
|
|
@@ -41,6 +41,9 @@ module Net; module SSH; module Transport
|
|
|
41
41
|
"camellia192-ctr@openssh.org" => "camellia-192-ecb",
|
|
42
42
|
"camellia256-ctr@openssh.org" => "camellia-256-ecb",
|
|
43
43
|
|
|
44
|
+
"aes256-gcm@openssh.com" => "aes-256-gcm",
|
|
45
|
+
"aes128-gcm@openssh.com" => "aes-128-gcm",
|
|
46
|
+
|
|
44
47
|
"none" => "none",
|
|
45
48
|
}
|
|
46
49
|
|
data/lib/net/ssh/version.rb
CHANGED
data/net-ssh.gemspec
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = "net-ssh"
|
|
8
|
-
s.version = "2.9.
|
|
8
|
+
s.version = "2.9.1"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Jamis Buck", "Delano Mandelbaum"]
|
|
12
12
|
s.cert_chain = ["gem-public_cert.pem"]
|
|
13
|
-
s.date = "2014-
|
|
13
|
+
s.date = "2014-05-13"
|
|
14
14
|
s.description = "Net::SSH: a pure-Ruby implementation of the SSH2 client protocol. It allows you to write programs that invoke and interact with processes on remote servers, via SSH2."
|
|
15
15
|
s.email = "net-ssh@solutious.com"
|
|
16
16
|
s.extra_rdoc_files = [
|
|
@@ -129,6 +129,7 @@ Gem::Specification.new do |s|
|
|
|
129
129
|
"test/configs/exact_match",
|
|
130
130
|
"test/configs/host_plus",
|
|
131
131
|
"test/configs/multihost",
|
|
132
|
+
"test/configs/negative_match",
|
|
132
133
|
"test/configs/nohost",
|
|
133
134
|
"test/configs/numeric_host",
|
|
134
135
|
"test/configs/send_env",
|
|
@@ -138,6 +139,7 @@ Gem::Specification.new do |s|
|
|
|
138
139
|
"test/connection/test_session.rb",
|
|
139
140
|
"test/known_hosts/github",
|
|
140
141
|
"test/manual/test_forward.rb",
|
|
142
|
+
"test/manual/test_pageant.rb",
|
|
141
143
|
"test/start/test_connection.rb",
|
|
142
144
|
"test/start/test_options.rb",
|
|
143
145
|
"test/start/test_transport.rb",
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Tests for communication capability with Pageant (or KeeAgent)
|
|
3
|
+
# process, to include the case where it is running in different UAC
|
|
4
|
+
# context.
|
|
5
|
+
#
|
|
6
|
+
# To run:
|
|
7
|
+
# - Ensure that Pageant is running (not as administrator).
|
|
8
|
+
# - Open two command prompts, one as an administrator and one limited
|
|
9
|
+
# (normal).
|
|
10
|
+
# - Within each, from the root net/ssh project directory, execute:
|
|
11
|
+
# ruby -Ilib -Itest -rrubygems test/manual/test_pageant.rb
|
|
12
|
+
#
|
|
13
|
+
|
|
14
|
+
require 'common'
|
|
15
|
+
require 'net/ssh/authentication/agent'
|
|
16
|
+
|
|
17
|
+
module Authentication
|
|
18
|
+
|
|
19
|
+
class TestPageant < Test::Unit::TestCase
|
|
20
|
+
|
|
21
|
+
def test_agent_should_be_able_to_negotiate
|
|
22
|
+
assert_nothing_raised(Net::SSH::Authentication::AgentNotAvailable) { agent.negotiate! }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def agent(auto=:connect)
|
|
28
|
+
@agent ||= begin
|
|
29
|
+
agent = Net::SSH::Authentication::Agent.new
|
|
30
|
+
agent.connect! if auto == :connect
|
|
31
|
+
agent
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
data/test/test_config.rb
CHANGED
|
@@ -35,6 +35,12 @@ class TestConfig < Test::Unit::TestCase
|
|
|
35
35
|
assert !config.key?('rekeylimit')
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
def test_load_with_wild_card_and_negative_pattern_does_not_match
|
|
39
|
+
config = Net::SSH::Config.load(config(:negative_match), "test.host")
|
|
40
|
+
assert_equal 9876, config['port']
|
|
41
|
+
assert !config.key?('compression')
|
|
42
|
+
end
|
|
43
|
+
|
|
38
44
|
def test_for_should_load_all_files_and_translate_to_net_ssh_options
|
|
39
45
|
config = Net::SSH::Config.for("test.host", [config(:exact_match), config(:wild_cards)])
|
|
40
46
|
assert_equal 1234, config[:port]
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: net-ssh
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.9.
|
|
4
|
+
version: 2.9.1
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -38,7 +38,7 @@ cert_chain:
|
|
|
38
38
|
bkh3ZjNJSVVQZzdsc01DUnpPa1EvRkQ4N0JJM1YzU25GTm9UQ2RHZ25HajNq
|
|
39
39
|
Zlc0elJsTAppRnlhcmVGUEE4NGJ0UT09Ci0tLS0tRU5EIENFUlRJRklDQVRF
|
|
40
40
|
LS0tLS0K
|
|
41
|
-
date: 2014-
|
|
41
|
+
date: 2014-05-13 00:00:00.000000000 Z
|
|
42
42
|
dependencies:
|
|
43
43
|
- !ruby/object:Gem::Dependency
|
|
44
44
|
name: test-unit
|
|
@@ -193,6 +193,7 @@ files:
|
|
|
193
193
|
- test/configs/exact_match
|
|
194
194
|
- test/configs/host_plus
|
|
195
195
|
- test/configs/multihost
|
|
196
|
+
- test/configs/negative_match
|
|
196
197
|
- test/configs/nohost
|
|
197
198
|
- test/configs/numeric_host
|
|
198
199
|
- test/configs/send_env
|
|
@@ -202,6 +203,7 @@ files:
|
|
|
202
203
|
- test/connection/test_session.rb
|
|
203
204
|
- test/known_hosts/github
|
|
204
205
|
- test/manual/test_forward.rb
|
|
206
|
+
- test/manual/test_pageant.rb
|
|
205
207
|
- test/start/test_connection.rb
|
|
206
208
|
- test/start/test_options.rb
|
|
207
209
|
- test/start/test_transport.rb
|
metadata.gz.sig
CHANGED
|
Binary file
|