win32-sspi 0.0.1.rc1-x86-mingw32
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.
- checksums.yaml +7 -0
- data/License.txt +8 -0
- data/README.md +31 -0
- data/Rakefile +49 -0
- data/examples/sspi_negotiate_client.rb +42 -0
- data/examples/sspi_negotiate_server.rb +99 -0
- data/lib/win32-sspi.rb +2 -0
- data/lib/win32/sspi/api/client.rb +17 -0
- data/lib/win32/sspi/api/common.rb +133 -0
- data/lib/win32/sspi/api/server.rb +32 -0
- data/lib/win32/sspi/negotiate/client.rb +159 -0
- data/lib/win32/sspi/negotiate/server.rb +199 -0
- data/lib/win32/sspi/windows/constants.rb +36 -0
- data/lib/win32/sspi/windows/functions.rb +31 -0
- data/lib/win32/sspi/windows/misc.rb +24 -0
- data/lib/win32/sspi/windows/structs.rb +147 -0
- data/test/all_tests.rb +2 -0
- data/test/test_win32_sspi_negotiate_client.rb +417 -0
- data/test/test_win32_sspi_negotiate_server.rb +441 -0
- data/test/test_win32_sspi_structure_creates.rb +100 -0
- data/win32-sspi.gemspec +29 -0
- metadata +102 -0
@@ -0,0 +1,441 @@
|
|
1
|
+
########################################################################
|
2
|
+
# Tests for the Win32::SSPI::Negotiate::Server class.
|
3
|
+
########################################################################
|
4
|
+
require 'test-unit'
|
5
|
+
require 'win32/sspi/negotiate/server'
|
6
|
+
|
7
|
+
class TC_Win32_SSPI_Negotiate_Server < Test::Unit::TestCase
|
8
|
+
MockSpnegoToken = Random.new.bytes(128)
|
9
|
+
MockCredentialHandle = [777,888]
|
10
|
+
MockTimeStamp = [0x000000FF,0xFF000000]
|
11
|
+
MockContextHandle = [123,987]
|
12
|
+
MockSecBufferContent = Random.new.bytes(128)
|
13
|
+
ContextAttr = Windows::Constants::ISC_REQ_CONFIDENTIALITY |
|
14
|
+
Windows::Constants::ISC_REQ_REPLAY_DETECT |
|
15
|
+
Windows::Constants::ISC_REQ_CONNECTION
|
16
|
+
|
17
|
+
def setup
|
18
|
+
@server = Win32::SSPI::Negotiate::Server.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# assert helper to help remove test duplication
|
22
|
+
def assert_server_call_state(server)
|
23
|
+
ach_args = server.retrieve_state(:ach)
|
24
|
+
refute_nil ach_args
|
25
|
+
assert_equal 9, ach_args.length
|
26
|
+
|
27
|
+
asc_args = server.retrieve_state(:asc)
|
28
|
+
refute_nil asc_args
|
29
|
+
assert_equal 9, asc_args.length
|
30
|
+
|
31
|
+
cat_args = server.retrieve_state(:cat)
|
32
|
+
refute_nil cat_args
|
33
|
+
assert_equal 2, cat_args.length
|
34
|
+
|
35
|
+
dsc_args = server.retrieve_state(:dsc)
|
36
|
+
refute_nil dsc_args
|
37
|
+
assert_equal 1, dsc_args.length
|
38
|
+
|
39
|
+
fch_args = server.retrieve_state(:fch)
|
40
|
+
refute_nil fch_args
|
41
|
+
assert_equal 1, fch_args.length
|
42
|
+
|
43
|
+
fcb_args = server.retrieve_state(:fcb)
|
44
|
+
refute_nil fcb_args
|
45
|
+
assert_equal 1, fcb_args.length
|
46
|
+
|
47
|
+
assert_nil server.instance_variable_get(:@credentials_handle)
|
48
|
+
assert_nil server.instance_variable_get(:@context_handle)
|
49
|
+
end
|
50
|
+
|
51
|
+
def assert_base64_http_header(header,auth_type)
|
52
|
+
if Win32::SSPI::API::Common::AUTH_TYPE_NEGOTIATE == auth_type
|
53
|
+
assert_match( /\ANegotiate \p{Print}+={,2}\z/,header)
|
54
|
+
end
|
55
|
+
if Win32::SSPI::API::Common::AUTH_TYPE_NTLM == auth_type
|
56
|
+
assert_match( /\ANTLM \p{Print}+={,2}\z/,header)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_auth_type_basic_functionality
|
61
|
+
assert_respond_to(@server, :auth_type)
|
62
|
+
assert_respond_to(@server, :auth_type=)
|
63
|
+
assert_nothing_raised{ @server.auth_type }
|
64
|
+
assert_kind_of(String, @server.auth_type)
|
65
|
+
assert_equal Win32::SSPI::API::Common::AUTH_TYPE_NEGOTIATE, @server.auth_type
|
66
|
+
|
67
|
+
server = Win32::SSPI::Negotiate::Server.new(auth_type: "Kerberos")
|
68
|
+
assert_equal "Kerberos", server.auth_type
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_token_basic_functionality
|
72
|
+
assert_respond_to(@server, :token)
|
73
|
+
assert_nothing_raised{ @server.token }
|
74
|
+
assert_kind_of(String, @server.token)
|
75
|
+
assert_equal "", @server.token
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_username_and_domain_basic_functionality
|
79
|
+
assert_respond_to(@server, :username)
|
80
|
+
assert_nothing_raised{ @server.username }
|
81
|
+
assert_kind_of(String, @server.username)
|
82
|
+
assert_equal "", @server.username
|
83
|
+
assert_respond_to(@server, :domain)
|
84
|
+
assert_nothing_raised{ @server.domain }
|
85
|
+
assert_kind_of(String, @server.domain)
|
86
|
+
assert_equal "", @server.domain
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_acquire_handle_basic_functionality
|
90
|
+
assert_respond_to(@server, :acquire_handle)
|
91
|
+
assert_equal 0, @server.method(:acquire_handle).arity
|
92
|
+
assert_respond_to(@server, :acquire_credentials_handle)
|
93
|
+
assert_equal 9, @server.method(:acquire_credentials_handle).arity
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_accept_context_basic_functionality
|
97
|
+
assert_respond_to(@server, :accept_context)
|
98
|
+
assert_equal( -1, @server.method(:accept_context).arity)
|
99
|
+
assert_respond_to(@server, :accept_security_context)
|
100
|
+
assert_equal 9, @server.method(:accept_security_context).arity
|
101
|
+
assert_respond_to(@server, :complete_auth_token)
|
102
|
+
assert_equal 2, @server.method(:complete_auth_token).arity
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_query_attributes_basic_functionality
|
106
|
+
assert_respond_to(@server, :query_attributes)
|
107
|
+
assert_equal 0, @server.method(:query_attributes).arity
|
108
|
+
assert_respond_to(@server, :query_context_attributes)
|
109
|
+
assert_equal 3, @server.method(:query_context_attributes).arity
|
110
|
+
assert_respond_to(@server, :free_credentials_handle)
|
111
|
+
assert_equal 1, @server.method(:free_credentials_handle).arity
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_acquire_handle_invokes_windows_api_as_expected
|
115
|
+
server = Class.new(MockNegotiateServer).new
|
116
|
+
assert_nothing_raised{ @status = server.acquire_handle }
|
117
|
+
assert_equal Windows::Constants::SEC_E_OK, @status
|
118
|
+
|
119
|
+
# test acquire_credentials_handle
|
120
|
+
args = server.retrieve_state(:ach)
|
121
|
+
assert_equal 9, args.length, "unexpected args"
|
122
|
+
assert_nil args[0], "unexpected psz_principal"
|
123
|
+
assert_equal Win32::SSPI::API::Common::AUTH_TYPE_NEGOTIATE, args[1], "unexpected psz_package"
|
124
|
+
assert_equal Windows::Constants::SECPKG_CRED_INBOUND, args[2], "unexpected f_credentialuse"
|
125
|
+
assert_nil args[3], "unexpected pv_logonid"
|
126
|
+
assert_nil args[4], "unexpected p_authdata"
|
127
|
+
assert_nil args[5], "unexpected p_getkeyfn"
|
128
|
+
assert_nil args[6], "unexpected p_getkeyarg"
|
129
|
+
assert_kind_of Windows::Structs::CredHandle, args[7], "unexpected ph_newcredentials"
|
130
|
+
assert_equal MockCredentialHandle, args[7].marshal_dump
|
131
|
+
assert_kind_of Windows::Structs::TimeStamp, args[8], "unexpected pts_expiry"
|
132
|
+
assert_equal MockTimeStamp, args[8].marshal_dump
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_acquire_handle_memoizes_handle
|
136
|
+
server = Class.new(MockNegotiateServer).new
|
137
|
+
assert_nothing_raised{ server.acquire_handle }
|
138
|
+
assert_nothing_raised{ @status = server.acquire_handle }
|
139
|
+
assert_equal Windows::Constants::SEC_E_OK, @status
|
140
|
+
assert_equal 9, server.retrieve_state(:ach).length
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_acquire_handle_raises_when_windows_api_returns_failed_status
|
144
|
+
server = Class.new(MockNegotiateServer) do
|
145
|
+
def acquire_credentials_handle(*args)
|
146
|
+
capture_state(:ach, args)
|
147
|
+
return Windows::Constants::SEC_E_SECPKG_NOT_FOUND
|
148
|
+
end
|
149
|
+
end.new
|
150
|
+
assert_raises(SecurityStatusError){ server.acquire_handle }
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_accept_context_invokes_windows_api_as_expected
|
154
|
+
server = Class.new(MockNegotiateServer).new
|
155
|
+
assert_nothing_raised{ server.acquire_handle }
|
156
|
+
assert_nothing_raised{ @status = server.accept_context(MockSpnegoToken) }
|
157
|
+
assert_equal Windows::Constants::SEC_E_OK, @status
|
158
|
+
|
159
|
+
args = server.retrieve_state(:asc)
|
160
|
+
assert_equal 9, args.length, "unexpected args"
|
161
|
+
assert_kind_of Windows::Structs::CredHandle, args[0], "unexpected ph_credentials"
|
162
|
+
assert_equal MockCredentialHandle, args[0].marshal_dump
|
163
|
+
assert_nil args[1], "unexpected ph_context"
|
164
|
+
assert_kind_of Windows::Structs::SecBufferDesc, args[2], "unexpected p_input"
|
165
|
+
assert_equal ContextAttr, args[3], "unexpected f_contextreq"
|
166
|
+
assert_equal Windows::Constants::SECURITY_NATIVE_DREP, args[4], "unexpected targetdatarep"
|
167
|
+
assert_kind_of Windows::Structs::CtxtHandle, args[5], "unexpected ph_newcontext"
|
168
|
+
assert_equal MockContextHandle, args[5].marshal_dump
|
169
|
+
assert_kind_of Windows::Structs::SecBufferDesc, args[6], "unexpected p_output"
|
170
|
+
assert_equal MockSecBufferContent, server.token
|
171
|
+
assert_kind_of FFI::MemoryPointer, args[7], "unexpected pf_contextattr"
|
172
|
+
assert_equal ContextAttr, args[7].read_ulong
|
173
|
+
assert_kind_of Windows::Structs::TimeStamp, args[8], "unexpected pts_expiry"
|
174
|
+
assert_equal MockTimeStamp, args[8].marshal_dump
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_accept_context_raises_when_windows_api_returns_failed_status
|
178
|
+
server = Class.new(MockNegotiateServer) do
|
179
|
+
def accept_security_context(*args)
|
180
|
+
capture_state(:asc, args)
|
181
|
+
return Windows::Constants::SEC_E_SECPKG_NOT_FOUND
|
182
|
+
end
|
183
|
+
end.new
|
184
|
+
assert_raises(SecurityStatusError){ server.accept_context }
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_complet_auth_invokes_windows_api_as_expected
|
188
|
+
server = Class.new(MockNegotiateServer) do
|
189
|
+
def accept_security_context(*args)
|
190
|
+
super
|
191
|
+
return Windows::Constants::SEC_I_COMPLETE_NEEDED
|
192
|
+
end
|
193
|
+
end.new
|
194
|
+
|
195
|
+
assert_nothing_raised{ server.acquire_handle }
|
196
|
+
assert_nothing_raised{ server.accept_context(MockSpnegoToken) }
|
197
|
+
assert_nothing_raised{ @status=server.complete_authentication }
|
198
|
+
assert_equal Windows::Constants::SEC_E_OK, @status
|
199
|
+
|
200
|
+
args = server.retrieve_state(:cat)
|
201
|
+
assert_equal 2, args.length
|
202
|
+
assert_kind_of Windows::Structs::CtxtHandle, args[0], "unexpected ph_context"
|
203
|
+
assert_equal MockContextHandle, args[0].marshal_dump
|
204
|
+
assert_kind_of Windows::Structs::SecBufferDesc, args[1], "unexpected p_output"
|
205
|
+
assert_equal MockSecBufferContent, args[1].marshal_dump
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_complet_auth_raises_when_windows_api_returns_failed_status
|
209
|
+
server = Class.new(MockNegotiateServer) do
|
210
|
+
def accept_security_context(*args)
|
211
|
+
super
|
212
|
+
return Windows::Constants::SEC_I_COMPLETE_NEEDED
|
213
|
+
end
|
214
|
+
def complete_auth_token(*args)
|
215
|
+
capture_state(:cat,args)
|
216
|
+
return Windows::Constants::SEC_E_INVALID_HANDLE
|
217
|
+
end
|
218
|
+
end.new
|
219
|
+
|
220
|
+
assert_nothing_raised{ server.acquire_handle }
|
221
|
+
assert_nothing_raised{ server.accept_context(MockSpnegoToken) }
|
222
|
+
assert_raises(SecurityStatusError){ server.complete_authentication }
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_query_attributes_invokes_windows_api_as_expected
|
226
|
+
server = Class.new(MockNegotiateServer).new
|
227
|
+
assert_nothing_raised{ server.acquire_handle }
|
228
|
+
assert_nothing_raised{ server.accept_context(MockSpnegoToken) }
|
229
|
+
assert_nothing_raised{ @status = server.query_attributes }
|
230
|
+
assert_equal Windows::Constants::SEC_E_OK, @status
|
231
|
+
|
232
|
+
args = server.retrieve_state(:qca)
|
233
|
+
assert_equal 3, args.length
|
234
|
+
assert_kind_of Windows::Structs::CtxtHandle, args[0], "unexpected ph_context"
|
235
|
+
assert_equal MockContextHandle, args[0].marshal_dump
|
236
|
+
assert_equal Windows::Constants::SECPKG_ATTR_NAMES, args[1], "unexpected ul_attribute"
|
237
|
+
assert_kind_of Windows::Structs::SecPkgContext_Names, args[2], "unexpected p_buffer"
|
238
|
+
|
239
|
+
assert_equal "jimmy", server.username
|
240
|
+
assert_equal "jes.local", server.domain
|
241
|
+
|
242
|
+
# Need to grap this address for test below
|
243
|
+
expected_fcb_ptr = args[2].to_username_ptr
|
244
|
+
|
245
|
+
args = server.retrieve_state(:fcb)
|
246
|
+
assert_equal 1, args.length
|
247
|
+
assert_equal expected_fcb_ptr, args[0], "unexpected pv_contextbuffer"
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_query_attributes_without_domain_in_user_string
|
251
|
+
server = Class.new(MockNegotiateServer) do
|
252
|
+
def query_context_attributes(*args)
|
253
|
+
super
|
254
|
+
args[2].marshal_load("jimmy")
|
255
|
+
return Windows::Constants::SEC_E_OK
|
256
|
+
end
|
257
|
+
end.new
|
258
|
+
assert_nothing_raised{ server.acquire_handle }
|
259
|
+
assert_nothing_raised{ server.accept_context(MockSpnegoToken) }
|
260
|
+
assert_nothing_raised{ @status = server.query_attributes }
|
261
|
+
assert_equal Windows::Constants::SEC_E_OK, @status
|
262
|
+
assert_equal "jimmy", server.username
|
263
|
+
assert_equal "", server.domain
|
264
|
+
end
|
265
|
+
|
266
|
+
def test_query_attributes_raises_when_windows_api_returns_failed_status
|
267
|
+
server = Class.new(MockNegotiateServer) do
|
268
|
+
def query_context_attributes(*args)
|
269
|
+
capture_state(:asc, args)
|
270
|
+
return Windows::Constants::SEC_E_INVALID_HANDLE
|
271
|
+
end
|
272
|
+
end.new
|
273
|
+
assert_raises(SecurityStatusError){ server.query_attributes }
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_free_handles_raises_when_free_handle_returns_failed_status
|
277
|
+
server = Class.new(MockNegotiateServer) do
|
278
|
+
def free_credentials_handle(*args)
|
279
|
+
capture_state(:fch,args)
|
280
|
+
return Windows::Constants::SEC_E_INVALID_HANDLE
|
281
|
+
end
|
282
|
+
end.new
|
283
|
+
|
284
|
+
assert_nothing_raised{ server.acquire_handle }
|
285
|
+
assert_nothing_raised{ server.accept_context(MockSpnegoToken) }
|
286
|
+
assert_nothing_raised{ server.query_attributes }
|
287
|
+
assert_raises(SecurityStatusError){ server.free_handles }
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_both_handles_freed_when_free_handles_raises
|
291
|
+
server = Class.new(MockNegotiateServer) do
|
292
|
+
def delete_security_context(*args)
|
293
|
+
capture_state(:dsc, args)
|
294
|
+
return Windows::Constants::SEC_E_INVALID_TOKEN
|
295
|
+
end
|
296
|
+
end.new
|
297
|
+
|
298
|
+
assert_nothing_raised{ server.acquire_handle }
|
299
|
+
assert_nothing_raised{ server.accept_context(MockSpnegoToken) }
|
300
|
+
|
301
|
+
refute_nil server.instance_variable_get(:@context_handle)
|
302
|
+
refute_nil server.instance_variable_get(:@credentials_handle)
|
303
|
+
|
304
|
+
assert_raises{ server.free_handles }
|
305
|
+
|
306
|
+
assert_nil server.instance_variable_get(:@context_handle)
|
307
|
+
assert_nil server.instance_variable_get(:@credentials_handle)
|
308
|
+
end
|
309
|
+
|
310
|
+
def test_http_authenticate
|
311
|
+
server = Class.new(MockNegotiateServer) do
|
312
|
+
def accept_security_context(*args)
|
313
|
+
status = self.retrieve_state(:asc) ?
|
314
|
+
Windows::Constants::SEC_I_COMPLETE_NEEDED :
|
315
|
+
Windows::Constants::SEC_I_CONTINUE_NEEDED
|
316
|
+
super
|
317
|
+
return status
|
318
|
+
end
|
319
|
+
end.new
|
320
|
+
|
321
|
+
counter = 0
|
322
|
+
authenticated = false
|
323
|
+
until( authenticated )
|
324
|
+
header = "#{Win32::SSPI::API::Common::AUTH_TYPE_NEGOTIATE} #{Base64.strict_encode64(MockSpnegoToken)}"
|
325
|
+
authenticated = server.http_authenticate(header) do |hdr|
|
326
|
+
counter += 1
|
327
|
+
fail "loop failed to complete in a reasonable iteration count" if counter > 3
|
328
|
+
assert_base64_http_header(hdr,Win32::SSPI::API::Common::AUTH_TYPE_NEGOTIATE)
|
329
|
+
hdr
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
assert_equal 2, counter
|
334
|
+
|
335
|
+
assert_server_call_state(server)
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_authenticate
|
339
|
+
server = Class.new(MockNegotiateServer) do
|
340
|
+
def accept_security_context(*args)
|
341
|
+
status = self.retrieve_state(:asc) ?
|
342
|
+
Windows::Constants::SEC_I_COMPLETE_NEEDED :
|
343
|
+
Windows::Constants::SEC_I_CONTINUE_NEEDED
|
344
|
+
super
|
345
|
+
return status
|
346
|
+
end
|
347
|
+
end.new
|
348
|
+
|
349
|
+
counter = 0
|
350
|
+
authenticated = false
|
351
|
+
until( authenticated )
|
352
|
+
client_msg = MockSpnegoToken
|
353
|
+
authenticated = server.authenticate(client_msg) do |msg|
|
354
|
+
counter += 1
|
355
|
+
fail "loop failed to complete in a reasonable iteration count" if counter > 3
|
356
|
+
assert_equal MockSecBufferContent,msg
|
357
|
+
msg
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
assert_equal 2, counter
|
362
|
+
|
363
|
+
assert_server_call_state(server)
|
364
|
+
end
|
365
|
+
|
366
|
+
def teardown
|
367
|
+
@server = nil
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
class MockNegotiateServer < Win32::SSPI::Negotiate::Server
|
372
|
+
def acquire_credentials_handle(*args)
|
373
|
+
s_args = retrieve_state(:ach) || Array.new
|
374
|
+
s_args << args
|
375
|
+
capture_state(:ach,s_args.flatten)
|
376
|
+
# this api should return a credential handle in arg[7] and a timestamp in arg[8]
|
377
|
+
args[7].marshal_load(TC_Win32_SSPI_Negotiate_Server::MockCredentialHandle)
|
378
|
+
args[8].marshal_load(TC_Win32_SSPI_Negotiate_Server::MockTimeStamp)
|
379
|
+
return Windows::Constants::SEC_E_OK
|
380
|
+
end
|
381
|
+
|
382
|
+
def accept_security_context(*args)
|
383
|
+
capture_state(:asc, args)
|
384
|
+
# this api should return a new context, p_output, context attr and timestamp
|
385
|
+
args[5].marshal_load(TC_Win32_SSPI_Negotiate_Server::MockContextHandle)
|
386
|
+
args[6].marshal_load(TC_Win32_SSPI_Negotiate_Server::MockSecBufferContent)
|
387
|
+
args[7].write_ulong(TC_Win32_SSPI_Negotiate_Server::ContextAttr)
|
388
|
+
args[8].marshal_load(TC_Win32_SSPI_Negotiate_Server::MockTimeStamp)
|
389
|
+
return Windows::Constants::SEC_E_OK
|
390
|
+
end
|
391
|
+
|
392
|
+
def complete_auth_token(*args)
|
393
|
+
capture_state(:cat,args)
|
394
|
+
return Windows::Constants::SEC_E_OK
|
395
|
+
end
|
396
|
+
|
397
|
+
def query_context_attributes(*args)
|
398
|
+
capture_state(:qca,args)
|
399
|
+
args[2].marshal_load("jes.local\\jimmy")
|
400
|
+
return Windows::Constants::SEC_E_OK
|
401
|
+
end
|
402
|
+
|
403
|
+
def delete_security_context(*args)
|
404
|
+
capture_state(:dsc,args)
|
405
|
+
return Windows::Constants::SEC_E_OK
|
406
|
+
end
|
407
|
+
|
408
|
+
def free_credentials_handle(*args)
|
409
|
+
capture_state(:fch,args)
|
410
|
+
return Windows::Constants::SEC_E_OK
|
411
|
+
end
|
412
|
+
|
413
|
+
def free_context_buffer(*args)
|
414
|
+
capture_state(:fcb,args)
|
415
|
+
return Windows::Constants::SEC_E_OK
|
416
|
+
end
|
417
|
+
|
418
|
+
def capture_state(key,value)
|
419
|
+
self.class.capture_state(key,value)
|
420
|
+
end
|
421
|
+
|
422
|
+
def retrieve_state(key)
|
423
|
+
self.class.retrieve_state(key)
|
424
|
+
end
|
425
|
+
|
426
|
+
def self.state
|
427
|
+
@state ||= Hash.new
|
428
|
+
end
|
429
|
+
|
430
|
+
def self.capture_state(key,value)
|
431
|
+
state[key] = value
|
432
|
+
end
|
433
|
+
|
434
|
+
def self.retrieve_state(key)
|
435
|
+
state[key]
|
436
|
+
end
|
437
|
+
|
438
|
+
def self.clear_state
|
439
|
+
state.clear
|
440
|
+
end
|
441
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
########################################################################
|
2
|
+
# Tests for the Windows::API::create_xxx methods
|
3
|
+
########################################################################
|
4
|
+
require 'test-unit'
|
5
|
+
require 'win32/sspi/api/common'
|
6
|
+
|
7
|
+
class TC_Win32_SSPI_Negotiate_Client < Test::Unit::TestCase
|
8
|
+
include Win32::SSPI::API::Common
|
9
|
+
|
10
|
+
def test_create_sec_winnt_auth_identity
|
11
|
+
user,domain,password = %w[tom gas yadayadayada]
|
12
|
+
identity = create_sec_winnt_auth_identity(user,domain,password)
|
13
|
+
assert_equal user, identity[:User].read_string
|
14
|
+
assert_equal user.length, identity[:UserLength]
|
15
|
+
assert_equal user, identity.user_to_ruby_s
|
16
|
+
assert_equal domain, identity[:Domain].read_string
|
17
|
+
assert_equal domain.length, identity[:DomainLength]
|
18
|
+
assert_equal domain, identity.domain_to_ruby_s
|
19
|
+
assert_equal password, identity[:Password].read_string
|
20
|
+
assert_equal password.length, identity[:PasswordLength]
|
21
|
+
assert_equal SEC_WINNT_AUTH_IDENTITY_ANSI, identity[:Flags]
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_create_credhandle
|
25
|
+
h_credential = create_credhandle(777,888)
|
26
|
+
assert_equal 777, h_credential[:dwLower].read_ulong
|
27
|
+
assert_equal 888, h_credential[:dwUpper].read_ulong
|
28
|
+
assert_equal [777,888], h_credential.marshal_dump
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_create_ctxhandle
|
32
|
+
h_ctx = create_ctxhandle(777,888)
|
33
|
+
assert_equal 777, h_ctx[:dwLower].read_ulong
|
34
|
+
assert_equal 888, h_ctx[:dwUpper].read_ulong
|
35
|
+
assert_equal [777,888], h_ctx.marshal_dump
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_create_timestamp
|
39
|
+
ts = create_timestamp(0xFFAA8811,0x00000044)
|
40
|
+
assert_equal 0xFFAA8811, ts[:dwLowDateTime]
|
41
|
+
assert_equal 0x00000044, ts[:dwHighDateTime]
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_create_secbuffer
|
45
|
+
content = "test content"
|
46
|
+
buffer = create_secbuffer(content)
|
47
|
+
assert_equal content, buffer[:pvBuffer].read_string
|
48
|
+
assert_equal content.length, buffer[:cbBuffer]
|
49
|
+
assert_equal SECBUFFER_TOKEN, buffer[:BufferType]
|
50
|
+
|
51
|
+
buffer = create_secbuffer
|
52
|
+
assert_not_nil buffer[:pvBuffer]
|
53
|
+
assert_equal TOKENBUFSIZE, buffer[:cbBuffer]
|
54
|
+
assert_equal SECBUFFER_TOKEN, buffer[:BufferType]
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_create_secbufferdesc
|
58
|
+
content = "test content"
|
59
|
+
buffer = create_secbuffer(content)
|
60
|
+
bufdesc = create_secbufferdesc(buffer)
|
61
|
+
assert_equal FFI::Pointer.new(buffer.pointer), bufdesc[:pBuffers]
|
62
|
+
assert_equal 1, bufdesc[:cBuffers]
|
63
|
+
assert_equal SECBUFFER_VERSION, bufdesc[:ulVersion]
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_create_secpkg_context_names
|
67
|
+
name ="test"
|
68
|
+
spkg_names = create_secpkg_context_names(name)
|
69
|
+
assert_equal name, spkg_names[:sUserName].read_string
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_to_ruby_s_accessors
|
73
|
+
content = "test content"
|
74
|
+
buffer = create_secbuffer(content)
|
75
|
+
assert_equal content, buffer.to_ruby_s
|
76
|
+
|
77
|
+
# FIXME: something un-intuitive about this ...
|
78
|
+
buffer = create_secbuffer
|
79
|
+
assert_equal TOKENBUFSIZE, buffer.to_ruby_s.length
|
80
|
+
|
81
|
+
name ="test"
|
82
|
+
spkg_names = create_secpkg_context_names(name)
|
83
|
+
assert_equal name, spkg_names.to_ruby_s
|
84
|
+
|
85
|
+
spkg_names = create_secpkg_context_names
|
86
|
+
assert_nil spkg_names.to_ruby_s
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_construct_de_construct_http_header
|
90
|
+
srand(Time.now.to_i)
|
91
|
+
tokenA = (1..40).inject([]) {|m,r| m << rand(255)}.join('')
|
92
|
+
header = construct_http_header(Win32::SSPI::API::Common::AUTH_TYPE_NEGOTIATE, tokenA)
|
93
|
+
assert_equal Win32::SSPI::API::Common::AUTH_TYPE_NEGOTIATE, header[0,9]
|
94
|
+
assert_match( /\A\p{Print}+\Z/, header)
|
95
|
+
|
96
|
+
auth_type, tokenB = de_construct_http_header(header)
|
97
|
+
assert_equal Win32::SSPI::API::Common::AUTH_TYPE_NEGOTIATE, auth_type
|
98
|
+
assert_equal tokenA, tokenB
|
99
|
+
end
|
100
|
+
end
|